bzoj 2243 [SDOI2011]染色
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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
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
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
Source
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;
}

浙公网安备 33010602011771号