1. 程式人生 > 其它 >【USACO 2021JAN G】Dance Mooves

【USACO 2021JAN G】Dance Mooves

USACOG

【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;
}