【bzoj4530】[Bjoi2014]大融合 并查集+线段树合并

线段树合并好神啊,表示我这种傻逼只能想到树剖O(nlog^2n)做法
先把原树建出来,每次查询就等价于计算子节点的size*(父亲节点所在联通块的大小-子节点的size)
用并查集找到节点的祖先,维护子树size
这个东西可以用线段树合并来做,查询就是查询dfs序上的一段区间

好像LCT+启发式合并更快?


#include
#include
#include
#include
#include
#include
#define maxn 200010
#define N 2000010

using namespace std;

struct yts
{
	int op,x,y;
}q[maxn];

int n,T,in[maxn],out[maxn],tot,num,cnt;
int root[maxn],lch[N],rch[N],size[N],g[maxn],f[maxn],dep[maxn];
int head[maxn],to[maxn],next[maxn];
char s[5];

void addedge(int x,int y)
{
	num++;to[num]=y;next[num]=head[x];head[x]=num;
}

int find(int x)
{
	if (f[x]==x) return x;
	else return f[x]=find(f[x]);
}

void modify(int &i,int l,int r,int x)
{
	if (!i) i=++cnt;
	if (l==r) {size[i]=1;return;}
	int mid=(l+r)/2;
	if (x<=mid) modify(lch[i],l,mid,x);
	if (middep[y]) swap(x,y);
			root[x]=merge(root[x],root[y]);
			f[y]=x;
		}
		else
		{
			int x=q[i].x,y=q[i].y;
			if (dep[x]


你可能感兴趣的:(数据结构)