BZOJ 2243: [SDOI2011]染色(树链剖分+线段树区间合并)

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

思路:
树链剖分,线段树维护区间内颜色段数以及左端点和右端点的颜色,
在链上进行区间合并时注意细节。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,tol;
int head[maxn],seg[maxn],rev[maxn],top[maxn],fa[maxn];
int Size[maxn],son[maxn],dep[maxn],a[maxn],add[maxn<<2];
struct RODE
{
	int to,next;
}rode[maxn*2];
struct TREE
{
	int lc,rc,sum;
}tree[maxn<<2];
void add_edge(int a,int b)
{
	rode[tol].to=b;
	rode[tol].next=head[a];
	head[a]=tol++;
}
void dfs1(int v,int father)
{
	Size[v]=1;
	dep[v]=dep[father]+1;
	fa[v]=father;
	for(int i=head[v];i!=-1;i=rode[i].next)
	{
		RODE e=rode[i];
		if(e.to==father)continue;
		dfs1(e.to,v);
		Size[v]+=Size[e.to];
		if(Size[son[v]]<Size[e.to]) son[v]=e.to;
	}
}
void dfs2(int v,int father)
{
	if(son[v])
	{
		seg[son[v]]=++seg[0];
		rev[seg[0]]=son[v];
		top[son[v]]=top[v];
		dfs2(son[v],v);
	}
	for(int i=head[v];i!=-1;i=rode[i].next)
	{
		RODE e=rode[i];
		if(!top[e.to])
		{
			seg[e.to]=++seg[0];
			rev[seg[0]]=e.to;
			top[e.to]=e.to;
			dfs2(e.to,v);
		}
	}
}
void push_down(int rt)
{
	if(add[rt]!=-1)
	{
		tree[rt<<1].sum=1;
		tree[rt<<1].lc=tree[rt<<1].rc=add[rt];
		tree[rt<<1|1].sum=1;
		tree[rt<<1|1].lc=tree[rt<<1|1].rc=add[rt];
		add[rt<<1]=add[rt<<1|1]=add[rt];
		add[rt]=-1;
	}
}
TREE Union(TREE x,TREE y)
{
	TREE v;
	v.lc=x.lc;
	v.rc=y.rc;
	v.sum=x.sum+y.sum;
	if(x.rc==y.lc) v.sum--;
	return v;
}
void build(int l,int r,int rt)
{
	if(l==r)
	{
		tree[rt].sum=1;
		tree[rt].lc=tree[rt].rc=a[rev[l]];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	tree[rt]=Union(tree[rt<<1],tree[rt<<1|1]);
}
void update(int L,int R,int C,int l,int r,int rt)
{
	if(l>=L&&r<=R)
	{
		add[rt]=C;
		tree[rt].sum=1;
		tree[rt].lc=tree[rt].rc=C;
		return;
	}
	push_down(rt);
	int mid=(l+r)/2;
	if(L<=mid) update(L,R,C,l,mid,rt<<1);
	if(R>mid) update(L,R,C,mid+1,r,rt<<1|1);
	tree[rt]=Union(tree[rt<<1],tree[rt<<1|1]);
}
TREE query(int L,int R,int l,int r,int rt)
{
	TREE v1,v2;
	v1.lc=v1.rc=-1; v1.sum=0;
	if(l>=L&&r<=R) return tree[rt];
	push_down(rt);
	int mid=(l+r)/2;
	if(L<=mid&&R>mid)
	{
		v1=query(L,R,l,mid,rt<<1);
		v2=query(L,R,mid+1,r,rt<<1|1);
		return Union(v1,v2);
	}
	else if(L<=mid) return query(L,R,l,mid,rt<<1);
	else if(R>mid) return query(L,R,mid+1,r,rt<<1|1);
	else return v1;
}
void change(int x,int y,int z)
{
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
		update(seg[fx],seg[x],z,1,seg[0],1);
		x=fa[fx],fx=top[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	update(seg[x],seg[y],z,1,seg[0],1);
}
int work(int x,int y)
{
	if(x==y) return 1;
	TREE v1,v2,v3;
	v1.lc=v1.rc=v2.lc=v2.rc=-1;
	v1.sum=v2.sum=0;
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(dep[fx]>dep[fy])
		{
			v3=query(seg[fx],seg[x],1,seg[0],1);
			//swap(v3.lc,v3.rc);
			v1=Union(v3,v1);
			x=fa[fx];fx=top[x];
		}
		else
		{
			v3=query(seg[fy],seg[y],1,seg[0],1);
			v2=Union(v3,v2);
			y=fa[fy];fy=top[y];
		}
	}
	if(dep[x]<dep[y])
	{
		v3=query(seg[x],seg[y],1,seg[0],1);
		v2=Union(v3,v2);
	}
	if(dep[x]>=dep[y])
	{
		v3=query(seg[y],seg[x],1,seg[0],1);
		//swap(v3.lc,v3.rc);
		v1=Union(v3,v1);
	}
	swap(v1.lc,v1.rc);
	return Union(v1,v2).sum;
}
int main()
{
	memset(add,-1,sizeof(add));
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;scanf("%d%d",&x,&y);
		add_edge(x,y);add_edge(y,x);
	}
	dfs1(1,0);
	seg[0]=seg[1]=rev[1]=top[1]=1;
	dfs2(1,0);
	build(1,seg[0],1);
	while(m--)
	{
		char t[2];int x,y,z;scanf("%s",&t);
		if(t[0]=='C')
		{
			scanf("%d%d%d",&x,&y,&z);
			change(x,y,z);
		}
		else
		{
			scanf("%d%d",&x,&y);
			printf("%d\n",work(x,y));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/81263699