【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;
}
posted @ 2021-08-19 20:42  冰雾  阅读(77)  评论(0编辑  收藏  举报