BZOJ 2243

http://www.lydsy.com/JudgeOnline/showsource.php?id=2443124

树链剖分套线段树直接肝

注意合并过程

#include<cstdio>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i) 
#define gc getchar()
using std::swap;
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
const int N=800011;
char S[5];
int c[N];
int n,m,dfn_num,x,y,z;
inline int read(){
	char c;while(c=gc,c==' '||c=='\n');int data=c-48;
	while(c=gc,c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48;return data;
}
struct edge{
    int to;
    edge *nxt;
    #define to(it) it->to
    #define add(x,y) (*++et=(edge){y,las[x]},las[x]=et)
    #define VIS(now) for(edge *it=las[now];it;it=it->nxt)
}e[N],*las[N],*et=e;
namespace Segment_Tree{
	struct Tree{
		int lc,rc,sum,tag;
	}tr[N];
	inline void push_up(int k){
		tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
		tr[k].lc=tr[k<<1].lc;tr[k].rc=tr[k<<1|1].rc;
		if(tr[k<<1].rc==tr[k<<1|1].lc)--tr[k].sum;
	}
	inline void push_down(int k){
		if(!tr[k].tag)return;
		tr[k<<1].lc=tr[k<<1].rc=tr[k<<1|1].lc=tr[k<<1|1].rc=tr[k<<1].tag=tr[k<<1|1].tag=tr[k].tag;
		tr[k<<1].sum=tr[k<<1|1].sum=1;
		tr[k].tag=0;
	}
	inline void change(int k,int x,int y,int v,int l=1,int r=n){
		push_down(k);
		if(x<=l&&r<=y){
			tr[k].sum=1;
			tr[k].tag=tr[k].lc=tr[k].rc=v;
			return;
		}
		int mid=(l+r)>>1;
		if(x<=mid)change(k<<1,x,y,v,l,mid);
		if(mid<y)change(k<<1|1,x,y,v,mid+1,r);
		push_up(k);
	}
	inline int query(int k,int x,int y,int l=1,int r=n){
		push_down(k);
		push_up(k);
		if(x<=l&&r<=y)return tr[k].sum;
		int mid=(l+r)>>1,ans=0;
		if(x<=mid)ans+=query(k<<1,x,y,l,mid);
		if(mid<y)ans+=query(k<<1|1,x,y,mid+1,r);
		if(x<=mid&&mid<y&&tr[k<<1].rc==tr[k<<1|1].lc)--ans;
		return ans;
	}
	inline int query_color(int k,int pos,int l=1,int r=n){
		push_down(k);
		push_up(k);
		if(l==r)return tr[k].lc;
		int mid=(l+r)>>1;
		return pos<=mid?query_color(k<<1,pos,l,mid):query_color(k<<1|1,pos,mid+1,r);
	}
};
using namespace Segment_Tree;
namespace TCP{
	int dep[N],sz[N],fa[N];
	int top[N],xu[N];
	inline void dfs1(int now){
		sz[now]=1;
		VIS(now)
			if(!dep[to(it)]){
				dep[to(it)]=dep[now]+1;fa[to(it)]=now;
				dfs1(to(it));sz[now]+=sz[to(it)];
			}
	}
	inline void dfs2(int now,int chain){
		register int i=0;
		top[now]=chain;xu[now]=++dfn_num;
		change(1,xu[now],xu[now],c[now]);
		VIS(now)if(dep[to(it)]>dep[now]&&sz[i]<sz[to(it)])i=to(it);
		if(!i)return;
		dfs2(i,chain);
		VIS(now)if(dep[to(it)]>dep[now]&&to(it)!=i)dfs2(to(it),to(it));
	}
	inline int up_query(int x,int y){
		int ans=0;
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			ans+=query(1,xu[top[x]],xu[x]);
			if(query_color(1,xu[top[x]])==query_color(1,xu[fa[top[x]]]))--ans;
			x=fa[top[x]];	
		}
		if(dep[x]>dep[y])swap(x,y);
		ans+=query(1,xu[x],xu[y]);
		return ans;
	}
	inline void up_change(int x,int y,int z){
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			change(1,xu[top[x]],xu[x],z);
			x=fa[top[x]];
		}
		if(dep[x]>dep[y])swap(x,y);
		change(1,xu[x],xu[y],z);
	}
};
using namespace TCP;
int main(){
	n=read();m=read();
	FOR(i,1,n)c[i]=read()+1;
	FOR(i,2,n){
		x=read();y=read();
		add(x,y);add(y,x);
	}
	dep[1]=1;dfs1(1);dfs2(1,1);
	while(m--){
		scanf("%s",S);
		x=read();y=read();
		if(S[0]=='Q')
			printf("%d\n",up_query(x,y));
		else{
			z=read()+1;
			up_change(x,y,z);
		}
	}
	return 0;
}

  

posted @ 2017-12-06 22:17  Stump  阅读(165)  评论(0编辑  收藏  举报