分块WA on #12 求hank
查看原帖
分块WA on #12 求hank
201748
cinccout楼主2023/2/7 14:38

萌新刚学分块口胡用并查集解决,给每个块内每种值分别开点,并给每个值开点连向它的值。

整块修改如果 y 存在就将 x 值的点连到 y ,否则把代表 x 的点变成代表 y 的点。散块如果没有 y 新建节点,然后暴力连边。代码如下:

#include<bits/stdc++.h>
using namespace std;
int fa[1000005],pos[500][105],d[200005],k,n,tot;
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline int rs(int i){return min(n,k*i);}
inline int ls(int i){return k*(i-1)+1;}
int a[200005];
int main()
{
	int q,l,r,x,y;cin>>n;k=sqrt(n);tot=n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);d[i]=(i-1)/k+1;
		if(!pos[d[i]][a[i]]) pos[d[i]][a[i]]=++tot,fa[tot]=tot;
		fa[i]=pos[d[i]][a[i]];
	}
	cin>>q;while(q--)
	{
		scanf("%d%d%d%d",&l,&r,&x,&y);
		if(x==y) continue;int L=d[l],R=d[r];
		if(L==R)
		{
			if(!pos[L][y]||fa[pos[L][y]]!=pos[L][y]) pos[L][y]=++tot,fa[tot]=tot;
			for(int i=l;i<=r;i++) if(find(i)==pos[L][x]) fa[i]=pos[L][y];
			continue;
		}
		for(int i=L+1;i<=R-1;i++)
		{
			if(!pos[i][x]) continue;
			if(!pos[i][y]||fa[pos[i][y]]!=pos[i][y]) pos[i][y]=pos[i][x],pos[i][x]=0;
			else fa[pos[i][x]]=pos[i][y];
		}
		if(!pos[L][y]||fa[pos[L][y]]!=pos[L][y]) pos[L][y]=++tot,fa[tot]=tot;
		if(!pos[R][y]||fa[pos[R][y]]!=pos[R][y]) pos[R][y]=++tot,fa[tot]=tot;
		for(int i=l;i<=rs(L);i++) if(find(i)==pos[L][x]) fa[i]=pos[L][y];
		for(int i=ls(R);i<=r;i++) if(find(i)==pos[R][x]) fa[i]=pos[R][y];
	}
	for(int i=1;i<=n;i++)
	{
		int xx=find(i);
		for(int j=1;j<=100;j++)
		{
			if(pos[d[i]][j]==xx)
			{
				printf("%d ",j);
				break;
			}
		}
	}
	return 0;
}

QAQ

2023/2/7 14:38
加载中...