版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前言
还是对模式循环行走问题不熟悉
回忆起跳房子,都是按照他所给的方法模拟会超时,就算找到循环节也会超时,于是由于地图固定,可以处理出一些点的下一个特征点,具体问题具体分析,也可以为分块
题目
Atcoder
题目大意:
思路
首先是暴力,模拟栈找循环节即可,会
然后我们怎么想呢,这种问题一般是一段一段地跨,我们多用暴力程序分析一下就会发现如果我们到一个位置
,我们可以处理出和它值一样的下一个位置
,于是下一个位置就是
(到了
处理一下) ,我们假设对
连边,就是一个
个点
条边的有向图,每个点的出度为1,但是我们要证明每个点入度为1,假设存在这样的图:
我们可以得到
两种情况,此时会发现B会连向A或者A会连向B,但是此时在环上保证了
,矛盾,于是每个点入度只能为1,于是
组成许多个环。
于是如果我们通过
进行遍历的话最多
次会回到 1,形成了循环,但如果次数并不够我们跳一圈(并不是进行一次操作,是循环次数) 我们就用
一步一步走,考虑如果只剩一次,假设现在在
就判断哪些点
输出即可
实现用的破环成链
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
LL read(){
bool f=0;LL x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return !f?x:-x;
}
#define MAXN 200000
#define INF 0x3f3f3f3f
bool vis[MAXN+5];
int n,a[MAXN+5],val[MAXN+5],nxt[MAXN+5];
void Print(int p){
while(p<=n){
if(nxt[p]>n) printf("%d ",a[p]),p++;
else p=nxt[p]+1;
}
puts("");
exit(0);
}
int main(){
n=read();
LL k=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=2*n;i>=n+1;i--)
val[a[i-n]]=i;
for(int i=n;i>=1;i--)
nxt[i]=val[a[i]],val[a[i]]=i;
int p=1;
LL sum=0;
while(!vis[p]){
sum+=nxt[p]-p,vis[p]=1;
if(nxt[p]>n)
p=(nxt[p]-n)%n+1;
else p=nxt[p]%n+1;
}
k%=(sum/n+1);
while(k){
if(!k) break;
if(k==1) Print(p);
if(nxt[p]>=n){
k--;
if(nxt[p]==2*n) k--;
p=(nxt[p]-n)%n+1;
}
else p=nxt[p]+1;
}
puts("");
return 0;
}