bzoj 2243 [SDOI2011]染色

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 8655  Solved: 3239
[Submit][Status][Discuss]

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

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

Sample Input

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

Sample Output

3
1
2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

Source

第一轮day1

 

Solution

树链剖分

线段树里面维护区间段数,区间左端点的颜色,区间右端点的颜色

询问的时候,合并两段要看它们连接的部分是否相同,我把那个左右搞反了,因为上面的点的编号小一点,所以上面是左

唔,最后一段要同时衔接左边段,和右边段,所以两边端点都要判断是否与最后一段相等

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
#define nn 100011
using namespace std;
int dfn[nn],wo[nn],fir[nn],nxt[nn<<1],to[nn<<1],size[nn],top[nn],fa[nn],son[nn],dep[nn],color[nn],li,e;
struct tree{
	int l,r,numco,lco,rco,z;
}t[nn<<2];
struct qu{
	int num,lco,rco;
}zc;
int read()
{
	int ans=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
	return ans*f;
}
void add(int u,int v)
{
	nxt[++e]=fir[u];fir[u]=e;to[e]=v;       ///
	nxt[++e]=fir[v];fir[v]=e;to[e]=u;
}
void dfs(int x)
{
	size[x]=1;
	for(int i=fir[x];i;i=nxt[i])
	  if(to[i]!=fa[x])
	  {
	  	fa[to[i]]=x;
	  	dfs(to[i]);
	  	if(size[to[i]]>size[son[x]])
	  	  son[x]=to[i];
	  	size[x]+=size[to[i]];
	  }
}
void dfs2(int x)
{
	if(son[x])
	{
		dep[son[x]]=dep[x]+1;
		dfn[++li]=son[x];
		wo[son[x]]=li;
		top[son[x]]=top[x];
		dfs2(son[x]);
	}
	for(int i=fir[x];i;i=nxt[i])
	  if(to[i]!=son[x]&&to[i]!=fa[x])
	  {
	  	dep[to[i]]=dep[x]+1;
	  	dfn[++li]=to[i];
	  	wo[to[i]]=li;
	  	top[to[i]]=to[i];
	  	dfs2(to[i]);
	  }
}
void updata(int k)
{
	t[k].lco=t[k<<1].lco;
	t[k].rco=t[k<<1|1].rco;
	t[k].numco=t[k<<1].rco==t[k<<1|1].lco? t[k<<1].numco+t[k<<1|1].numco-1:t[k<<1].numco+t[k<<1|1].numco;
}
void build(int k,int l,int r)
{
	t[k].l=l;t[k].r=r;
	if(l==r)
	{
		t[k].numco=1;
		t[k].lco=color[dfn[l]];
		t[k].rco=color[dfn[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	updata(k);
}
void pushdown(int k)
{
	t[k<<1].lco=t[k].z;t[k<<1].rco=t[k].z;t[k<<1].numco=1;t[k<<1].z=t[k].z;
	t[k<<1|1].lco=t[k].z;t[k<<1|1].rco=t[k].z;t[k<<1|1].numco=1;t[k<<1|1].z=t[k].z;
	t[k].z=0; 
}
void modify(int k,int l,int r,int c)
{
	if(t[k].l==l&&t[k].r==r)
	{
		t[k].numco=1;
		t[k].lco=c;
		t[k].rco=c;
		t[k].z=c;
		return;
	}
	if(t[k].z)
	  pushdown(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(r<=mid)
	  modify(k<<1,l,r,c);
	else if(l>mid)
	  modify(k<<1|1,l,r,c);
	else
	{
		modify(k<<1,l,mid,c);
		modify(k<<1|1,mid+1,r,c);
	}
	updata(k);
}
qu query(int k,int l,int r)
{
	if(t[k].l==l&&t[k].r==r)
	{
		qu o;
		o.lco=t[k].lco;
		o.rco=t[k].rco;
		o.num=t[k].numco;
		return o;
	}
	if(t[k].z)
	  pushdown(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(r<=mid)
	  return query(k<<1,l,r);
	else if(l>mid)
	  return query(k<<1|1,l,r);
	else
	{
		qu oo,oe;
		oo=query(k<<1,l,mid);
		oe=query(k<<1|1,mid+1,r);
		oo.num+=oe.num;
		if(oo.rco==oe.lco)
		  oo.num--;
		oo.rco=oe.rco;
		return oo;
	}
}
void revise(int a,int b,int c)
{
	while(top[a]!=top[b])
	{
		if(dep[top[a]]<dep[top[b]])
		  swap(a,b);
		modify(1,wo[top[a]],wo[a],c);
		a=fa[top[a]];
	}
	if(dep[a]>dep[b])
	  swap(a,b);
	modify(1,wo[a],wo[b],c);
}
int ask(int a,int b)
{
	int res=0,prea=-1,preb=-1;
	while(top[a]!=top[b])
	{
		if(dep[top[a]]>dep[top[b]])
		{
			zc=query(1,wo[top[a]],wo[a]);
			res+=zc.num;
			if(prea>=0&&prea==zc.rco)
			  res--;
			prea=zc.lco;         ///反了 
			a=fa[top[a]];
		}
		else
		{
			zc=query(1,wo[top[b]],wo[b]);
			res+=zc.num;
			if(preb>=0&&preb==zc.rco)
			  res--;
			preb=zc.lco;
			b=fa[top[b]];
		}
	}
	if(dep[a]<dep[b])
	{
		zc=query(1,wo[a],wo[b]);
		res+=zc.num;
		if(prea>=0&&prea==zc.lco)
		  res--;
		if(preb>=0&&preb==zc.rco)
		  res--;
	}
	else
	{
		zc=query(1,wo[b],wo[a]);
		res+=zc.num;
		if(preb>=0&&preb==zc.lco)
		  res--;
		if(prea>=0&&prea==zc.rco)
		  res--;
	}
	return res;
}
int main()
{
	char opt;
	int n,m,a,b,c,u,v;
	n=read();m=read();
	for(int i=1;i<=n;i++)
	  color[i]=read();
	for(int i=1;i<n;i++)
	{
		u=read();v=read();add(u,v);
	}
	dfs(1);
	top[1]=1;
	dep[1]=1;
	dfn[++li]=1;wo[1]=li;
	dfs2(1);
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		opt=getchar();
		while(opt!='C'&&opt!='Q')
		  opt=getchar();
		a=read();b=read();
		if(opt=='C')
		{
			c=read();
			revise(a,b,c);
		}
		else
		  printf("%d\n",ask(a,b));
	}
	return 0;
}
posted @ 2017-10-19 20:37  o00v00o  阅读(114)  评论(0编辑  收藏  举报