专栏文章
题解:AT_agc036_b [AGC036B] Do Not Duplicate
AT_agc036_b题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min8dxa5
- 此快照首次捕获于
- 2025/12/01 22:15 3 个月前
- 此快照最后确认于
- 2025/12/01 22:15 3 个月前
看到删除操作就可以往这么一个方向上去想了:
设 代表如果从 开始插入,之后环形插入,第一次出现删空之后再往 里面加数,加入的第一个数的位置。(这里的位置可能会 ,因为我们在记录位置的同时要记录是第几次走到这里,这样才能应对 轮的变化)
之后直接暴力跳下一个位置。通过打表可以发现通过跳跃位置作为边建出的图是若干个环,因为每一个点都有正好一个入度、一个出度。
通过周期缩环的方式将 次循环操作改为 次操作。因为周期长度必然 。紧接着在环上的每一个点暴力跳跃,直到即将超过 步。此时还剩下 步,裸暴力跳跃即可。
时间复杂度为 ,但未完全理解就会觉得它很抽象。
CPP#include<bits/stdc++.h>
#define int long long
#define mp(a,b) make_pair(a,b)
using namespace std;
inline int read(){
int a=0,b=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-') b=-1;
c=getchar();
}
while(isdigit(c)){
a=(a<<1)+(a<<3)+(c-'0');
c=getchar();
}
return a*b;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>=10) write(x/10);
putchar(x%10+48);
}
inline void write1(int x){
write(x),putchar(' ');
}
inline void write2(int x){
write(x),putchar('\n');
}
//找从 1 开始的循环节
const int N=1e6+15;
int n,m,k;
int a[N];
int nxt[N];
int nxt_sum[N]; //按数值划分的 nxt
int lst[N];
int stk[N];
int stk_idx;
#undef int
int main(){
#define int long long
n=read(),k=read(),m=n*k;
for(int i=1;i<=n;i++){
a[i]=a[i+n]=a[i+2*n]=read();
}
//在 long long 范围内 大多数内容都是能够去完成的!
for(int i=3*n;i>=1;i--){
nxt[i]=nxt_sum[a[i]]+1;
nxt_sum[a[i]]=i; //代表未来它会出现的位置
//实际上要对环进行各种改造
}
// for(int i=1;i<=n;i++){
// cout<<nxt[i]<<' ';
// }
// cout<<endl;
int now=1;
int circle=0; //代表一个经过点的环长
int circle_=0; //环长 但是要除以数组长度
do{
circle+=nxt[now]-now;
// cout<<'$'<<circle<<endl;
now=nxt[now];
while(now>n) now-=n;
// cout<<'$'<<circle<<' '<<now<<endl;
}while(now!=1);
// return 0;
// cout<<circle<<endl;
circle_=circle/n;
// cout<<'&'<<circle<<' '<<circle_<<endl;
k%=circle_; //大幅减小环的数目!
// cout<<'*'<<k<<endl;
m=n*k; //距离终点还有最后 m 步!!!!!
int m1=m;
now=1;//!!!!!
while(1){
if(m<nxt[now]-now) break; //在这里把它弹出!
m-=nxt[now]-now;
now=nxt[now]; //继续跳上去!
while(now>n) now-=n;
// if(now==1) break;
}
// m=m1-m;
// m1%=m;
// return 0;
// cout<<m<<endl;
for(int i=m;i>=1;i--){
int now=n-i+1;
now=a[now];
int lst_=lst[now];
// cout<<'#'<<now<<' '<<lst_<<endl;
if(lst_!=0&&lst_<=stk_idx){
// cout<<"谭总的世界-017"<<endl;
for(int j=lst_;j<=stk_idx;j++){
lst[stk[j]]=0;
}
stk_idx=lst_-1;
}
else{
stk_idx++;
stk[stk_idx]=now;
lst[now]=stk_idx;
}
// cout<<'^'<<stk_idx<<endl;
// cout<<endl;
}
for(int i=1;i<=stk_idx;i++){
write1(stk[i]);
}
putchar('\n');
return 0;
} //一定要挽回罗琪钧的遗憾啊,一定会挽回罗琪钧的遗憾的!
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...