[Luogu 2486] SDOI2011 染色

[Luogu 2486] SDOI2011 染色

<题目链接>


树剖水题,线段树维护。

详细题解不写了。

我只想说我写的线段树又变漂亮了qwq


#include <algorithm>
#include <cstdio>
#include <cstring>
const int MAXN=100010;
int n,m;
class HLD
{
	private:
		bool vis[MAXN];
		int num;
		static int rank[MAXN];
		static struct Node
		{
			int v,depth,father,son,top,size,DFN;
		}s[MAXN];
		class SegmentTree
		{
			private:
				struct Node
				{
					int v,left,right,lazy,color[2];
					Node *c[2];
					Node(int l,int r):left(l),right(r),lazy(0)
					{
						memset(color,0,sizeof color);
						c[0]=c[1]=nullptr;
						if(l==r)
						{
							v=1;
							color[0]=color[1]=s[rank[l]].v;
							return;
						}
						int mid=l+r>>1;
						c[0]=new Node(l,mid);
						c[1]=new Node(mid+1,r);
						PushUp();
					}
					~Node(void)
					{
						if(c[0]!=nullptr)
							delete c[0];
						if(c[1]!=nullptr)
							delete c[1];
					}
					void Modify(int x)
					{
						v=1;
						lazy=color[0]=color[1]=x;
					}
					void PushUp(void)
					{
						v=c[0]->v+c[1]->v;
						color[0]=c[0]->color[0];
						color[1]=c[1]->color[1];
						if(c[0]->color[1]==c[1]->color[0])
							--v;
					}
					void PushDown(void)
					{
						if(c[0]!=nullptr)
							c[0]->Modify(lazy);
						if(c[1]!=nullptr)
							c[1]->Modify(lazy);
						lazy=0;
					}
					int Color(int x)
					{
						if(left==right)
							return color[0];
						if(lazy)
							PushDown();
						int mid=left+right>>1;
						if(x>mid)
							return c[1]->Color(x);
						else
							return c[0]->Color(x);
					}
					void Change(int l,int r,int v)
					{
						if(l==left && r==right)
						{
							Modify(v);
							return;
						}
						if(lazy)
							PushDown();
						int mid=left+right>>1;
						if(r<=mid)
							c[0]->Change(l,r,v);
						else if(l>mid)
							c[1]->Change(l,r,v);
						else
						{
							c[0]->Change(l,mid,v);
							c[1]->Change(mid+1,r,v);
						}
						PushUp();
					}
					int Query(int l,int r)
					{
						if(l==left && r==right)
							return v;
						int mid=left+right>>1;
						if(lazy)
							PushDown();
						if(r<=mid)
							return c[0]->Query(l,r);
						else if(l>mid)
							return c[1]->Query(l,r);
						else
						{
							int ans=c[0]->Query(l,mid)+c[1]->Query(mid+1,r);
							if(c[0]->color[1]==c[1]->color[0])
								--ans;
							return ans;
						}
					}
				}*root;
			public:
				SegmentTree(int n)
				{
					root=new Node(1,n);
				}
				~SegmentTree(void)
				{
					delete root;
				}
				int Color(int x)
				{
					return root->Color(x);
				}
				void Change(int l,int r,int v)
				{
					root->Change(l,r,v);
				}
				int Query(int l,int r)
				{
					return root->Query(l,r);
				}
		}*T;
		struct Edge
		{
			int to;
			Edge *next;
			Edge(int to,Edge* next):to(to),next(next){}
			~Edge(void)
			{
				if(next!=nullptr)
					delete next;
			}
		}*head[MAXN];
		void AddEdges(int u,int v)
		{
			head[u]=new Edge(v,head[u]);
			head[v]=new Edge(u,head[v]);
		}
		void DFS1(int u,int k)
		{
			s[u].depth=k;
			s[u].size=1;
			int v;
			for(Edge *i=head[u];i!=nullptr;i=i->next)
				if(!s[v=i->to].size)
				{
					DFS1(v,k+1);
					s[v].father=u;
					s[u].size+=s[v].size;
					if(s[v].size>s[s[u].son].size)
						s[u].son=v;
				}
		}
		void DFS2(int u,int top)
		{
			s[u].top=top;
			s[u].DFN=++num;
			rank[num]=u;
			vis[u]=true;
			if(s[u].son)
				DFS2(s[u].son,top);
			int v;
			for(Edge *i=head[u];i!=nullptr;i=i->next)
				if(!vis[v=i->to])
					DFS2(v,v);
		}
	public:
		HLD(int n):num(0)
		{
			memset(s,0,sizeof s);
			std::fill(head+1,head+n+1,nullptr);
			for(int i=1;i<=n;++i)
				scanf("%d",&s[i].v);
			for(int i=1,u,v;i<n;++i)
			{
				scanf("%d %d",&u,&v);
				AddEdges(u,v);
			}
			DFS1(1,1);
			DFS2(1,1);
			T=new SegmentTree(n);
		}
		~HLD(void)
		{
			for(int i=1;i<=n;++i)
				delete head[i];
			delete T;
		}
		void Change(int x,int y)
		{
			int a,b,v;
			scanf("%d",&v);
			while((a=s[x].top)^(b=s[y].top))
				if(s[a].depth>s[b].depth)
				{
					T->Change(s[a].DFN,s[x].DFN,v);
					x=s[a].father;
				}
				else
				{
					T->Change(s[b].DFN,s[y].DFN,v);
					y=s[b].father;
				}
			if(s[x].depth<s[y].depth)
				T->Change(s[x].DFN,s[y].DFN,v);
			else
				T->Change(s[y].DFN,s[x].DFN,v);
		}
		void Query(int x,int y)
		{
			int a,b,ans=0;
			while((a=s[x].top)^(b=s[y].top))
				if(s[a].depth>s[b].depth)
				{
					ans+=T->Query(s[a].DFN,s[x].DFN);
					x=s[a].father;
					if(T->Color(s[a].DFN)==T->Color(s[x].DFN))
						--ans;
				}
				else
				{
					ans+=T->Query(s[b].DFN,s[y].DFN);
					y=s[b].father;
					if(T->Color(s[b].DFN)==T->Color(s[y].DFN))
						--ans;
				}
			ans+=s[x].depth<s[y].depth ? T->Query(s[x].DFN,s[y].DFN) : T->Query(s[y].DFN,s[x].DFN);
			printf("%d\n",ans);
		}
}*T;
int HLD::rank[MAXN];
HLD::Node HLD::s[MAXN];
int main(int argc,char** argv)
{
	scanf("%d %d",&n,&m);
	T=new HLD(n);
	char c;
	for(int i=1,x,y;i<=m;++i)
	{
		scanf("\n%c %d %d",&c,&x,&y);
		if(c=='C')
			T->Change(x,y);
		else
			T->Query(x,y);
	}
	delete T;
	return 0;
}

谢谢阅读。

posted @ 2018-06-16 19:51  Capella  阅读(137)  评论(0编辑  收藏  举报

谢谢光临