【USACO 2021JAN G】Dance Mooves
阿新 • • 發佈:2021-08-19
USACOG
,\(Q=MmodK\)
【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\)
每個點在環上走一步需\(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; }