bzoj2243[SDOI2011]染色

bzoj2243[SDOI2011]染色

题意:

n点无根树,2类操作:将节点a到节点b路径上所有点都染成颜色c、询问节点a到节点b路径上的颜色段数量。

题解:

有点恶心的链剖,可以用包含区间颜色段数,左端点颜色,右端点颜色的结构体存储查询的结果。首先是线段树节点除了要保存区间颜色段数还要保存左右端点颜色,再者是查询的时候要注意合并区间:在线段树查询时,如果递归左端点,就左合并递归结果,如果右端点就右合并;在树链查询时,从下往上左合并查询结果,两段分开处理,当两段都查询完时将一段的结果中的左右端点颜色交换,然后合并。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #define inc(i,j,k) for(int i=j;i<=k;i++)
  5 #define maxn 200000
  6 using namespace std;
  7 
  8 struct e{int t,n;}; e es[maxn];int ess,g[maxn];
  9 void pe(int f,int t){es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;}
 10 int fa[maxn],sz[maxn],dep[maxn],pos[maxn],top[maxn],v[maxn][2],sgs;
 11 int l[maxn*4],r[maxn*4],ch[maxn*4][2],ll[maxn*4],rr[maxn*4],sm[maxn*4],tg[maxn*4];
 12 struct nd{
 13     int sm,l,r;
 14     void plusr(nd d){
 15         sm=sm+d.sm+(r==d.l?-1:0); r=d.r;
 16     }
 17     void plusl(nd d){
 18         sm=sm+d.sm+(d.r==l?-1:0); l=d.l;
 19     }
 20 };
 21 void dfs(int x){
 22     sz[x]=1; for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]){
 23         dep[es[i].t]=dep[x]+1; fa[es[i].t]=x; dfs(es[i].t); sz[x]+=sz[es[i].t];
 24     }
 25 }
 26 void buildchain(int x,int ps){
 27     pos[x]=++sgs; top[x]=ps; v[sgs][1]=v[x][0]; int mx1,mx2=0;
 28     for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&mx2<sz[es[i].t])mx2=sz[es[i].t],mx1=es[i].t;
 29     if(mx2)buildchain(mx1,ps);
 30     for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&es[i].t!=mx1)buildchain(es[i].t,es[i].t);
 31 }
 32 int lca(int x,int y){
 33     for(;top[x]!=top[y];x=fa[top[x]])if(dep[top[x]]<dep[top[y]])swap(x,y);
 34     return dep[x]<dep[y]?x:y;
 35 }
 36 void update(int x){
 37     if(!x)return; if(!ch[x][0]&&!ch[x][1])sm[x]=0;
 38     sm[x]=sm[ch[x][0]]+sm[ch[x][1]]+(rr[ch[x][0]]==ll[ch[x][1]]?-1:0);
 39     ll[x]=ll[ch[x][0]]; rr[x]=rr[ch[x][1]];
 40 }
 41 void pushdown(int x){
 42     if(!x||tg[x]==-1)return; int lc=ch[x][0],rc=ch[x][1];
 43     if(lc)sm[lc]=1,ll[lc]=rr[lc]=tg[x],tg[lc]=tg[x];
 44     if(rc)sm[rc]=1,ll[rc]=rr[rc]=tg[x],tg[rc]=tg[x]; tg[x]=-1;
 45 }
 46 void build(int x,int L,int R){
 47     if(L==R)l[x]=r[x]=L,ch[x][0]=ch[x][1]=0,ll[x]=rr[x]=v[L][1],tg[x]=-1,sm[x]=1;else{
 48         int M=(L+R)>>1; ch[x][0]=x<<1; ch[x][1]=x<<1|1; l[x]=L; r[x]=R; tg[x]=-1;
 49         build(ch[x][0],L,M); build(ch[x][1],M+1,R); update(x);
 50     }
 51 }
 52 nd query(int x,int L,int R){
 53     pushdown(x); if(L<=l[x]&&r[x]<=R)return (nd){sm[x],ll[x],rr[x]};
 54     int M=(l[x]+r[x])>>1; nd q;
 55     if(L<=M){
 56         q=query(ch[x][0],L,R); if(M<R)q.plusr(query(ch[x][1],L,R));
 57     }else if(M<R)q=(query(ch[x][1],L,R));
 58     return q;
 59 }
 60 void change(int x,int L,int R,int col){
 61     pushdown(x); if(L<=l[x]&&r[x]<=R){ll[x]=rr[x]=tg[x]=col,sm[x]=1; return;}
 62     int M=(l[x]+r[x])>>1; if(L<=M)change(ch[x][0],L,R,col);
 63     if(M<R)change(ch[x][1],L,R,col); update(x);
 64 }
 65 void init1(){ess=0; memset(g,0,sizeof(g));}
 66 void init2(){fa[1]=0; dep[1]=0; dfs(1); sgs=0; buildchain(1,1); build(1,1,sgs);}
 67 int querysum(int a,int b){
 68     if(a==b)return query(1,pos[a],pos[b]).sm; int c=lca(a,b);
 69     nd q1; bool f=0;
 70     while(dep[top[a]]>dep[top[c]]){
 71         if(!f)q1=query(1,pos[top[a]],pos[a]),f=1;else q1.plusl(query(1,pos[top[a]],pos[a]));
 72         a=fa[top[a]];
 73     }
 74     if(!f)q1=query(1,pos[c],pos[a]),f=1;else q1.plusl(query(1,pos[c],pos[a]));
 75     nd q2; f=0;
 76     while(dep[top[b]]>dep[top[c]]){
 77         if(! f)q2=query(1,pos[top[b]],pos[b]),f=1;else q2.plusl(query(1,pos[top[b]],pos[b]));
 78         b=fa[top[b]];
 79     }
 80     if(! f)q2=query(1,pos[c],pos[b]),f=1;else q2.plusl(query(1,pos[c],pos[b]));
 81     swap(q1.l,q1.r); q1.plusr(q2); return q1.sm;
 82 }
 83 void changecol(int a,int b,int col){
 84     if(a==b){change(1,pos[a],pos[b],col);} int c=lca(a,b);
 85     while(dep[top[a]]>dep[top[c]])change(1,pos[top[a]],pos[a],col),a=fa[top[a]];
 86     change(1,pos[c],pos[a],col);
 87     while(dep[top[b]]>dep[top[c]])change(1,pos[top[b]],pos[b],col),b=fa[top[b]];
 88     change(1,pos[c],pos[b],col);
 89 }
 90 int n,m; char op[3];
 91 int main(){
 92     //freopen("test.txt","r",stdin);
 93     scanf("%d%d",&n,&m); inc(i,1,n)scanf("%d",&v[i][0]); init1();
 94     inc(i,1,n-1){int a,b; scanf("%d%d",&a,&b); pe(a,b);} init2();
 95     inc(i,1,m){
 96         int a,b,c; scanf("%s%d%d",op,&a,&b);
 97         if(op[0]=='Q'){printf("%d\n",querysum(a,b));}
 98         if(op[0]=='C'){scanf("%d",&c); changecol(a,b,c);}
 99     }
100     return 0;
101 }

 

20160427

posted @ 2016-07-20 20:25  YuanZiming  阅读(150)  评论(0编辑  收藏  举报