【BZOJ2243】【SDOI2011】染色

Zarxdy34 posted @ 2016年1月14日 23:17 in BZOJ with tags 树链剖分 , 258 阅读

  挺裸的一道树链剖分。

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100010;

struct Tree
{
	struct Segment_Tree
	{
		int sum[maxn<<2];
		int lc[maxn<<2],rc[maxn<<2];
		int tag_same[maxn<<2],same[maxn<<2];
		int n;

		#define ls (o<<1)
		#define rs ((o<<1)|1)
		#define mid ((l+r)>>1)

		void Update(int o) {sum[o]=sum[ls]+sum[rs]-(rc[ls]==lc[rs]);lc[o]=lc[ls];rc[o]=rc[rs];}
		
		void Mark_Same(int o,int c) {lc[o]=rc[o]=c;sum[o]=1;tag_same[o]=1;same[o]=c;}

		void Push_Down(int o)
		{
			if (tag_same[o])
			{
				Mark_Same(ls,same[o]);
				Mark_Same(rs,same[o]);
				same[o]=tag_same[o]=0;
			}
		}

		void Build(int o,int l,int r,int *color)
		{
			if (l==r) {sum[o]=1;lc[o]=rc[o]=color[l];return;}
			Build(ls,l,mid,color);
			Build(rs,mid+1,r,color);
			Update(o);
		}

		void Change(int o,int l,int r,int a,int b,int c)
		{
			if (a<=l && r<=b) {Mark_Same(o,c);return;}
			Push_Down(o);
			if (a<=mid) Change(ls,l,mid,a,b,c);
			if (b> mid) Change(rs,mid+1,r,a,b,c);
			Update(o);
		}

		int Query(int o,int l,int r,int a,int b,int &lcolor,int &rcolor)
		{
			if (a<=l && r<=b) {lcolor=lc[o];rcolor=rc[o];return sum[o];}
			Push_Down(o);
			int res=0;
			if (a<=mid && b>mid)
			{
				int ll,lr,rl,rr;
				res+=Query(ls,l,mid,a,b,ll,lr);
				res+=Query(rs,mid+1,r,a,b,rl,rr);
				if (lr==rl) res--;
				lcolor=ll;rcolor=rr;
			}
			else if (a<=mid) res=Query(ls,l,mid,a,b,lcolor,rcolor);else res=Query(rs,mid+1,r,a,b,lcolor,rcolor);
			Update(o);
			return res;
		}
		#undef ls
		#undef rs
		#undef mid
		
		void Build(int *color) {Build(1,1,n,color);}
		void Change(int l,int r,int c) {Change(1,1,n,l,r,c);}
		int Query(int l,int r,int &lcolor,int &rcolor) {return Query(1,1,n,l,r,lcolor,rcolor);}
	}ST;

	int head[maxn],next[maxn<<1],E[maxn<<1],Ecnt;
	int fa[maxn],dep[maxn];
	int top[maxn],wson[maxn];
	int id[maxn],ids;
	int temp[maxn];

	void Add_Edge(int x,int y) {next[++Ecnt]=head[x];head[x]=Ecnt;E[Ecnt]=y;next[++Ecnt]=head[y];head[y]=Ecnt;E[Ecnt]=x;}

	int DFS1(int x,int father,int depth)
	{
		int sons=0,maxsons=0;
		fa[x]=father;dep[x]=depth;
		for (int i=head[x];i;i=next[i]) if (E[i]!=father)
		{
			int tsons=DFS1(E[i],x,depth+1);
			sons+=tsons;
			if (tsons>maxsons) maxsons=tsons,wson[x]=E[i];
		}
		return sons+1;
	}

	void DFS2(int x,int is_wson)
	{
		id[x]=++ids;
		if (is_wson) top[x]=top[fa[x]];else top[x]=x;
		if (wson[x]) DFS2(wson[x],1);
		for (int i=head[x];i;i=next[i]) if (E[i]!=fa[x] && E[i]!=wson[x]) DFS2(E[i],0);
	}

	#define fx (top[x])
	#define fy (top[y])

	void Change(int x,int y,int c)
	{
		while (fx!=fy)
		{
			if (dep[fx]<dep[fy]) swap(x,y);
			ST.Change(id[fx],id[x],c);
			x=fa[fx];
		}
		if (dep[x]>dep[y]) swap(x,y);
		ST.Change(id[x],id[y],c);
	}

	int Query(int x,int y)
	{
		int lc=0,rc=0,tcl=0,tcr=0,res=0;
		while (fx!=fy)
		{
			if (dep[fx]<dep[fy]) swap(x,y),swap(lc,rc);
			res+=ST.Query(id[fx],id[x],tcl,tcr);
			if (tcr==lc) res--;
			lc=tcl;x=fa[fx];
		}
		if (dep[x]>dep[y]) swap(x,y),swap(lc,rc);
		res+=ST.Query(id[x],id[y],tcl,tcr);
		res-=(tcl==lc)+(tcr==rc);
		return res;
	}

	#undef fx
	#undef fy

	void Init(int n,int *color) {DFS1(1,0,1);DFS2(1,0);ST.n=n;for (int i=1;i<=n;i++) temp[id[i]]=color[i];ST.Build(temp);}
}T;

char readchar() {char ch;while ((ch=getchar())!='Q' && ch!='C');return ch;}
void read(int &x) {char ch;while ((ch=getchar())<'0' || ch>'9');x=ch-'0';while ((ch=getchar())<='9' && ch>='0') x=x*10+ch-'0';}
int temp[maxn];
int n,m;

void Init()
{
	read(n),read(m);
	for (int i=1;i<=n;i++) read(temp[i]);
	for (int i=1,x,y;i<n;i++) read(x),read(y),T.Add_Edge(x,y);
	T.Init(n,temp);
}

void Solve()
{
	for (int i=1;i<=m;i++)
	{
		char ch=readchar();
		int a,b,c;
		if (ch=='C') read(a),read(b),read(c),T.Change(a,b,c);
		if (ch=='Q') read(a),read(b),printf("%d\n",T.Query(a,b));
	}
}

int main()
{
	Init();
	Solve();
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Copyright © 2007

Webdesign, tvorba www stránek

Valid XHTML 1.1