问一个关于加权并查集的细节,站外题
  • 板块学术版
  • 楼主Reunite
  • 当前回复4
  • 已保存回复4
  • 发布时间2022/11/21 21:12
  • 上次更新2023/10/27 02:01:21
查看原帖
问一个关于加权并查集的细节,站外题
377760
Reunite楼主2022/11/21 21:12

题面:

有n个格子,每个格子里可能有0/1/2三个数,共3^n中可能。
0和1在一起,剩下的是0
1和2在一起,剩下的是1
2和0在一起,剩下的是2
若两数相同,则原来在这个格子里的数存在,另一个消失
m次操作:
1 u v 把v号格子里的数放到u号格子,v号格子消失,   
	u,v里的数满足一上条件
2 u 询问使原来u号格子里的数存在的方案数(mod
	998244353)
注:操作一是永久影响
n,q<=2e5
input:
3 5
2 1
1 2 1
2 1
1 2 3
2 1
output:
27
9
6

这道题可以用带权并查集来写,权记录概率。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mod 998244353
using namespace std;

int n,m,cnt;
int fa[400005];
ll w[400005];

inline void in(int &n){
	n=0;
	char c=getchar();
	while(c<'0' || c>'9') c=getchar();
	while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
	return ;
}

inline ll calc(ll x,int k){
	ll tmp=1;
	while(k){
		if(k&1) tmp=tmp*x%mod;
		x=x*x%mod;
		k>>=1;
	}
	return tmp;
}

int Find(int x){
	if(fa[x]==x) return x;
	int fath=Find(fa[x]);
	w[x]=w[x]*w[fa[x]]%mod;
	return fa[x]=fath;
}

int main(){
	in(n),in(m);
	for(int i=1;i<=2*n;i++) fa[i]=i,w[i]=1;
	int op,u,v;
	cnt=n;
	ll ni=calc(3,mod-2);
	ll ci=calc(3,n);
	while(m--){
		in(op);
		if(op==1){
			in(u),in(v);
			int uu=Find(u),vv=Find(v);
			w[uu]=ni*2%mod;
			w[vv]=ni;
			fa[uu]=fa[vv]=++cnt;
		}
		else{
			in(u);
			Find(u);
			printf("%lld\n",ci*w[u]%mod);
		}
	} 
	
	return 0;
}

AC代码

可是op1那里改成这样

if(op==1){
	in(u),in(v);
	w[Find(u)]=ni*2%mod;
	w[Find(v)]=ni;
	fa[Find(u)]=fa[Find(v)]=++cnt;
}

就不对了!!?? 求解释

2022/11/21 21:12
加载中...