您的位置:首页 > 其它

【bzoj2243】[SDOI2011]染色

2017-03-19 10:17 369 查看
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]之间。

题解

树链剖分,线段树记录区间颜色段数,与左右两端颜色,这样就可以合并计算了。注意答案的统计。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
int n,m,tim,tot;
struct seg{int l;int r;int n;}t[400005];
int Head[100005],ret[200005],Next[200005],bl[100005];
int son[100005],size[100005],pos[100005],c[100005];
int fa[100005],dep[100005],lazy[400005];
using namespace std;
int read(){
int x=0,f=1;
char ch;
ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}

void ins(int u,int v){
tot++;ret[tot]=v;Next[tot]=Head[u];Head[u]=tot;
}

void init(){
n=read();m=read();
for (int i=1;i<=n;i++){
c[i]=read();
}
for (int i=1;i<n;i++){
int x=read(),y=read();
ins(x,y);ins(y,x);
}
}

void dfs1(int u){
size[u]=1;
for (int i=Head[u];i!=0;i=Next[i]){
int v=ret[i];
if (v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
size[u]+=size[v];
if (son[u]==0||size[son[u]]<size[v]){
son[u]=v;
}
}
}
}

void dfs2(int u,int chain){
tim++;
pos[u]=tim;
bl[u]=chain;
if (son[u]!=0){
dfs2(son[u],chain);
}
for (int i=Head[u];i!=0;i=Next[i]){
int v=ret[i];
if (v!=fa[u]&&v!=son[u]){
dfs2(v,v);
}
}
}

void pushdown(int k,int l,int r){
if (l==r) return;
int c=lazy[k];lazy[k]=-1;
t[k<<1].n=1;t[k<<1].l=c;t[k<<1].r=c;
t[k<<1|1].n=1;t[k<<1|1].l=c;t[k<<1|1].r=c;
lazy[k<<1]=c;lazy[k<<1|1]=c;
}

void change(int k,int l,int r,int x,int y,int color){
if (lazy[k]!=-1) pushdown(k,l,r);
if (l==x&&r==y){
t[k].l=color;
t[k].r=color;
t[k].n=1;
lazy[k]=color;
return;
}
int mid=(l+r)/2;
if (y<=mid) change(k<<1,l,mid,x,y,color);
if (x>mid) change(k<<1|1,mid+1,r,x,y,color);
if (x<=mid&&y>mid){
change(k<<1,l,mid,x,mid,color);
change(k<<1|1,mid+1,r,mid+1,y,color);
}
t[k].n=t[k<<1].n+t[k<<1|1].n;
t[k].l=t[k<<1].l;t[k].r=t[k<<1|1].r;
if (t[k<<1].r==t[k<<1|1].l) t[k].n--;
}

seg query(int k,int l,int r,int x,int y){
if (lazy[k]!=-1) pushdown(k,l,r);
if (l==x&&r==y){
return t[k];
}
int mid=(l+r)/2;
if (y<=mid) return query(k<<1,l,mid,x,y);
if (x>mid) return query(k<<1|1,mid+1,r,x,y);
seg a,b,c;
a=query(k<<1,l,mid,x,mid);
b=query(k<<1|1,mid+1,r,mid+1,y);
c.n=a.n+b.n;
if (a.r==b.l) c.n--;
c.l=a.l;c.r=b.r;
return c;
}

void solvechange(int a,int b,int c){
while (bl[a]!=bl[b]){
if (dep[bl[a]]<dep[bl[b]]) swap(a,b);
change(1,1,n,pos[bl[a]],pos[a],c);
a=fa[bl[a]];
}
if (pos[a]>pos[b]) swap(a,b);
change(1,1,n,pos[a],pos[b],c);
}

int solveask(int x,int y){
int ans=0;
seg a,b,c;
a.l=-1;a.r=-1;b.l=-1;b.r=-1;
while (bl[x]!=bl[y]){
if (dep[bl[x]]<dep[bl[y]]){
swap(x,y);
swap(a,b);
}
c=query(1,1,n,pos[bl[x]],pos[x]);
ans+=c.n;
if (c.r==a.l) ans--;
a=c;
x=fa[bl[x]];
}
if (pos[x]>pos[y]){
swap(x,y);
swap(a,b);
}
c=query(1,1,n,pos[x],pos[y]);
ans+=c.n;
if (c.l==a.l) ans--;
if (c.r==b.l) ans--;
return ans;
}

void solve(){
for (int i=1;i<=n;i++){
change(1,1,n,pos[i],pos[i],c[i]);
}
for (int i=1;i<=m;i++){
char ch[10];
scanf("%s",ch);
if (ch[0]=='C'){
int a=read(),b=read(),c=read();
solvechange(a,b,c);
}else{
int a=read(),b=read();
printf("%d\n",solveask(a,b));
}
}
}

int main(){
memset(lazy,-1,sizeof(lazy));
init();
dfs1(1);
dfs2(1,1);
solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: