【USACO 2021JAN G】Dance Mooves
【USACO 2021JAN G】Dance Mooves
by AmanoKumiko
Description
最初,\(N\)头奶牛排成一排,第\(i\)个位置上为第\(i\)头奶牛
现给出\(K\)对位置\((ai,bi)\)
第\(1\)分钟,\((a1,b1)\)交换位置
第\(2\)分钟,\((a2,b2)\)交换位置
\(...\)
第\(K+1\)分钟,\((a1,b1)\)交换位置
第\(K+2\)分钟,\((a2,b2)\)交换位置
以此类推
现经过\(M\)分钟,求每头奶牛经过位置的集合大小
Input
第一行\(N\),\(K\),\(M\)
以下\(K\)行包含\((a1,b1)...(ak,bk)\)
Output
\(N\)行,表示答案
Sample Input
6 4 7
1 2
2 3
3 4
4 5
Sample Output
5
4
3
3
3
1
Data Constraint
\(2 \le N \le 10^5,1 \le K \le 2*10^5,1 \le M \le 10^{18}\)
Solution
考虑没有\(M\)的限制的情况
先走\(K\)步,记录每头牛经过的点
每个点\(i\)向它最后到的点连边
这样会形成一个置换
有置换就有环
那求出每个环,每头牛的答案就是环上所有点能到达的点的集合
加上\(M\)的限制
令\(P=\lfloor\frac{M}{K}\rfloor\),\(Q=MmodK\)
每个点在环上走一步需\(K\)的时间
为防止算重,我们开个桶记录能到达的点,每次向滑动窗口一样维护
每次加一个点(的集合),删除一个点(的集合)
对于\(Q\),就是求环上走\(P\)步后到的点再进行\(Q\)次交换
我们在初始\(K\)次交换时记一个时间戳(因为此时无法跑满\(K\)次交换)
将其和\(Q\)比较大小,加入桶即可
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define Fs(i,x) for(auto i:a[x])
#define LL long long
#define N 200010
struct node{int val,ti;};
vector<node>a[N];
int n,u,v,cnt,tail,q[N*2],to[N],p[N],ans[N],tot[N],P,Q,tmp;
bool vis[N],flag;
LL k,m;
void insP(int x){if(!tot[x])tmp++;tot[x]++;}
void insS(int x){Fs(d,x)insP(d.val);}
void decP(int x){tot[x]--;if(!tot[x])tmp--;}
void decS(int x){Fs(d,x)decP(d.val);}
int main(){
scanf("%d%lld%lld",&n,&k,&m);
P=m/k;Q=m%k;flag=(m<=k);
F(i,1,n)p[i]=i,a[i].push_back((node){i,0});
F(i,1,min(m,k)){
scanf("%d%d",&u,&v);
a[p[u]].push_back((node){v,i});
a[p[v]].push_back((node){u,i});
swap(p[u],p[v]);
}
if(flag){F(i,1,n)insS(i),printf("%d\n",tmp),decS(i);return 0;}
F(i,1,n)to[p[i]]=i;
F(i,1,n)if(!vis[i]){
tmp=cnt=tail=0;
if(to[i]==i){insS(i);ans[i]=tmp;decS(i);continue;}
int now=i;while(!vis[now])vis[q[++cnt]=now]=1,now=to[now];
F(j,1,cnt)q[j+cnt]=q[j];
if(cnt<=P){
F(j,1,cnt)insS(q[j]);
F(j,1,cnt)ans[q[j]]=tmp;
F(j,1,cnt)decS(q[j]);
continue;
}
F(j,1,cnt){
while(tail+1<=j+P-1)insS(q[++tail]);
if(Q)Fs(d,q[j+P])if(d.ti<=Q)insP(d.val);
ans[q[j]]=tmp;
if(Q)Fs(d,q[j+P])if(d.ti<=Q)decP(d.val);
decS(q[j]);
}
F(j,cnt+1,tail)decS(q[j]);
}
F(i,1,n)printf("%d\n",ans[i]);
return 0;
}