bzoj2243: [SDOI2011]染色

来源:互联网 发布:蜂窝移动网络 启用4g 编辑:程序博客网 时间:2024/04/30 01:04

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 <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int maxn=300000+10;struct node{int cnum,cl,cr;int lazy;node(){cnum=0;cl=cr=lazy=-1;}}nd[maxn*8];int top[maxn],size[maxn],son[maxn];int fa[maxn],dep[maxn],tid[maxn];int td=0;vector<int>A[maxn];int color[maxn];int num[maxn];int n;inline void dfs1(int x,int d,int f){dep[x]=d;size[x]=1;fa[x]=f;for(int i=0;i<A[x].size();i++){int u=A[x][i];if(u==f)continue;dfs1(u,d+1,x);size[x]+=size[u];if(size[son[x]]<size[u])son[x]=u;}}inline void dfs2(int x,int tp){tid[x]=++td;top[x]=tp;if(!son[x])return ;dfs2(son[x],tp);for(int i=0;i<A[x].size();i++){int u=A[x][i];if(u==fa[x]||u==son[x])continue;dfs2(u,u);}}inline void pushdown(int o){if(nd[o].lazy!=-1){nd[o<<1].cnum=nd[o<<1|1].cnum=1;nd[o<<1].cl=nd[o<<1].cr=nd[o<<1|1].cl=nd[o<<1|1].cr=nd[o].lazy;nd[o<<1].lazy=nd[o<<1|1].lazy=nd[o].lazy;nd[o].lazy=-1;}}inline void pushup(int o){nd[o].cl=nd[o<<1].cl,nd[o].cr=nd[o<<1|1].cr;nd[o].cnum=nd[o<<1].cnum+nd[o<<1|1].cnum-(nd[o<<1].cr==nd[o<<1|1].cl);}inline void change(int o,int l,int r,int L,int R,int x){pushdown(o);if(L<=l&&r<=R){nd[o].lazy=x;nd[o].cl=nd[o].cr=x;nd[o].cnum=1;return ;}else {int mid=(l+r)>>1;if(mid>=L)change(o<<1,l,mid,L,R,x);if(mid<R)change(o<<1|1,mid+1,r,L,R,x);pushup(o);}}inline void build(int o,int l,int r){if(l==r){nd[o].cl=nd[o].cr=num[l];nd[o].lazy=-1,nd[o].cnum=1;return ;}else {int mid=(l+r)>>1;build(o<<1,l,mid);build(o<<1|1,mid+1,r);pushup(o);}}inline node query(int o,int l,int r,int L,int R){pushdown(o);if(L<=l&&r<=R)return nd[o];else {int mid=(l+r)>>1;node ll,rr,ans;if(mid>=L){ll=query(o<<1,l,mid,L,R);ans.cnum+=ll.cnum;ans.cl=ll.cl;ans.cr=ll.cr;}if(mid<R){rr=query(o<<1|1,mid+1,r,L,R);ans.cnum+=rr.cnum;if(ans.cl==-1)ans.cl=rr.cl;ans.cr=rr.cr;}if(ll.cnum&&rr.cnum){if(ll.cr==rr.cl)ans.cnum--;}return ans;}}inline int Query(int x,int y){int ans=0;int lstx=-1,lsty=-1;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]){swap(x,y);swap(lstx,lsty);}node ndd=query(1,1,n,tid[top[x]],tid[x]);ans+=ndd.cnum;if(lstx!=-1){if(ndd.cr==lstx)ans--;}lstx=ndd.cl;x=fa[top[x]];}if(dep[x]>dep[y]){swap(x,y);swap(lstx,lsty);}node ndd=query(1,1,n,tid[x],tid[y]);ans+=ndd.cnum;if(lsty!=-1){if(ndd.cr==lsty)ans--;}if(lstx!=-1){if(ndd.cl==lstx)ans--;}return ans;}inline void Change(int x,int y,int z){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);change(1,1,n,tid[top[x]],tid[x],z);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);change(1,1,n,tid[x],tid[y],z);}int main(){//int size = 50 << 20;//char *p = (char*)malloc(size) + size;//__asm__("movl %0, %%esp\n" :: "r"(p));//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);int m;scanf("%d %d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&color[i]);int x,y;for(int i=1;i<n;i++){scanf("%d %d",&x,&y);A[x].push_back(y);A[y].push_back(x);}dfs1(1,1,1);dfs2(1,1);for(int i=1;i<=n;i++)num[tid[i]]=color[i];build(1,1,n);char c;int z;while(m--){cin>>c;if(c=='C'){scanf("%d %d %d",&x,&y,&z);Change(x,y,z);}else {scanf("%d %d",&x,&y);printf("%d\n",Query(x,y));}}return 0;}

ps:我比较弱,bzoj上一直re,但luogu上ac了,如果有神犇知道是怎么回事请联系蒟蒻qwq

原创粉丝点击