P5689 [CSP-S2019 江西] 多叉堆

试着推了一下静态树的做法,推挂了。。。
考虑一个点接到另一个点会怎么样。
肯定要乘上两边的答案 \(ans_x\times ans_y\)。
然后发现有一部分分在新子树上,其余部分分在其他子树上。由于只考虑大小关系,所以 \(1 2 3\) 和 \(233 114514 1919810\) 本质上是一样的。对于两种堆不同当且仅当存在某个结点填入的值不同,可以依靠 \(C(sze_x,sze_x+sze_y-1)\) 解决。
所以可以解决合并的。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
#define int long long
int fa[maxn];
int fd(int x){
	return x==fa[x]?x:fa[x]=fd(fa[x]);
}
int n,q,Ans=0;
int sze[maxn],ans[maxn],jc[maxn];
const int mod=1e9+7; 
int ksm(int a,int b){
	if(b==1)return a;
	int ans=ksm(a,b>>1);
	if(b&1)return ans*ans%mod*a%mod;
	else return ans*ans%mod;
}
int ny(int x){
	return ksm(x,mod-2);
}
int C(int n,int m){
	return jc[m]*ny(jc[n])%mod*ny(jc[m-n])%mod;
}
signed main(){
	cin>>n>>q;
	for(int i=1;i<=q;i++)fa[i]=i;
	for(int i=1;i<=n;i++)ans[i]=1,sze[i]=1;
	jc[0]=1;
	for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i,jc[i]%=mod;
	for(int i=1;i<=q;i++){
		int ch,x,y;
		cin>>ch>>x;
		if(ch==1){
			cin>>y;
			x=(x+Ans)%n;y=(y+Ans)%n;
			x++,y++;
			int fx=fd(x),fy=fd(y);
			ans[fy]=ans[fx]*ans[fy]%mod*C(sze[fx],sze[fx]+sze[fy]-1)%mod;
			sze[fy]+=sze[fx];fa[fx]=fy;
		}
		else{
			x=(x+Ans)%n;
			cout<<ans[fd(x+1)]<<endl;
			Ans=ans[fd(x+1)];
		}
	}
	return 0;
} 
上一篇:【树链剖分】有序剖分模板


下一篇:安装e(fx)clipse到Eclipse