B20J_2243_[SDOI2011]染色_树链剖分+线段树

Posted fcwww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B20J_2243_[SDOI2011]染色_树链剖分+线段树相关的知识,希望对你有一定的参考价值。

B20J_2243_[SDOI2011]染色_树链剖分+线段树

一下午净调这题了,争取晚上多做几道。

题意:

给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
 
分析:
线段树结点维护信息:区间内颜色段数t ,区间左端点颜色lco,区间右端点颜色rco,延迟标记lazy
上传时lco[pos]=lco[lson];rco[pos]=rco[rson];t[pos]=t[lson]+t[rson];如果左区间右端点和右区间左端点颜色相同,t[pos]--;
查询时每次找到左右端点的颜色(直接单点查找),如果LC=RC,ans--;
注意每次标记下传的时机。
 
代码
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 using namespace std;
  5 #define N 1000010
  6 #define M 2062145
  7 #define lson pos<<1
  8 #define rson pos<<1|1
  9 int head[N],to[N<<1],nxt[N<<1],co[N],cnt,n,m,scc;
 10 char ch[10];
 11 int dep[N],fa[N],siz[N],son[N],top[N];
 12 int t[M],lzy[M],idx[N],lco[M],rco[M],a[N];
 13 inline void read(int &x)
 14 {
 15     int f=1;x=0;char s=getchar();
 16     while(s<0||s>9){if(s==-)f=-1;s=getchar();}
 17     while(s>=0&&s<=9){x=(x<<3)+(x<<1)+s-0;s=getchar();}
 18     x*=f;    
 19 }
 20 inline void add(int u,int v)
 21 {
 22     to[++cnt]=v;
 23     nxt[cnt]=head[u];
 24     head[u]=cnt;    
 25 }
 26 inline void dfs1(int x,int y)
 27 {
 28     dep[x]=dep[y]+1;
 29     fa[x]=y;
 30     siz[x]=1;
 31     for(int i=head[x];i;i=nxt[i])
 32     {
 33         if(to[i]!=y)
 34         {
 35             dfs1(to[i],x);
 36             siz[x]+=siz[to[i]];
 37             if(siz[to[i]]>siz[son[x]])
 38             {
 39                 son[x]=to[i];
 40             }
 41         }
 42     }
 43 }
 44 inline void dfs2(int x,int t)
 45 {
 46     top[x]=t;
 47     idx[x]=++scc;
 48     if(son[x])dfs2(son[x],t);
 49     for(int i=head[x];i;i=nxt[i])
 50     {
 51         if(to[i]!=fa[x]&&to[i]!=son[x])
 52         {
 53             dfs2(to[i],to[i]);
 54         }
 55     }
 56 }
 57 inline void pud(int pos)
 58 {
 59     if(!lzy[pos])return ;
 60     t[lson]=1;lzy[lson]=lco[lson]=rco[lson]=lzy[pos];    
 61     t[rson]=1;lzy[rson]=lco[rson]=rco[rson]=lzy[pos];
 62     lzy[pos]=0;    
 63 }
 64 inline void up(int l,int r,int pos,int x,int y,int c)
 65 {
 66     if(x<=l&&y>=r)
 67     {
 68         t[pos]=1;
 69         lco[pos]=c;
 70         rco[pos]=c;
 71         lzy[pos]=c;
 72         return ;
 73     }
 74     pud(pos);
 75     int mid=l+r>>1;
 76     if(x<=mid)up(l,mid,lson,x,y,c);
 77     if(y>mid)up(mid+1,r,rson,x,y,c);
 78     t[pos]=t[lson]+t[rson];
 79     if(lco[rson]==rco[lson])t[pos]--;
 80     lco[pos]=lco[lson];
 81     rco[pos]=rco[rson];    
 82 }
 83 inline int query(int l,int r,int pos,int x,int y)
 84 {
 85     pud(pos);
 86     int re=0;
 87     int mid=l+r>>1;
 88     if(x<=l&&y>=r)
 89     {
 90         return t[pos];
 91     }
 92     if(y<=mid) return query(l,mid,lson,x,y);
 93     else if(x>mid) return query(mid+1,r,rson,x,y);
 94     else 
 95     {
 96         re=query(l,mid,lson,x,y)+query(mid+1,r,rson,x,y);
 97         if(lco[rson]==rco[lson])re--;
 98         return re;    
 99     }
100 }
101 inline int col(int l,int r,int x,int pos)
102 {
103     pud(pos);
104     if(l==r)return     lco[pos];
105     int mid=l+r>>1;
106     if(x<=mid)return col(l,mid,x,lson);
107     else return col(mid+1,r,x,rson);
108 }
109 int main()
110 {
111     read(n),read(m);
112     int x,y,z;
113     register int i;
114     for(i=1;i<=n;++i)
115     {
116         read(a[i]);
117     }
118     for(i=1;i<n;++i)
119     {
120         read(x),read(y);
121         add(x,y);
122         add(y,x);
123     }
124     dfs1(1,0);
125     dfs2(1,1);
126     for(i=1;i<=n;++i)up(1,n,1,idx[i],idx[i],a[i]);
127     while(m--)
128     {
129         scanf("%s",ch);
130         if(ch[0]==C)
131         {
132             read(x),read(y),read(z);
133             while(top[x]!=top[y])
134             {
135                 if(dep[top[x]]>dep[top[y]])swap(x,y);
136                 up(1,n,1,idx[top[y]],idx[y],z);
137                 y=fa[top[y]];
138             }
139             if(dep[x]<dep[y])swap(x,y);
140             up(1,n,1,idx[y],idx[x],z);
141         }
142         else 
143         {
144             read(x),read(y);
145             int ans=0;
146             while(top[x]!=top[y])
147             {
148                 if(dep[top[x]]>dep[top[y]])swap(x,y);
149                 int LC=col(1,n,idx[top[y]],1),RC=col(1,n,idx[fa[top[y]]],1);
150                 ans+=query(1,n,1,idx[top[y]],idx[y]);
151                 if(LC==RC)ans--;    
152                 y=fa[top[y]];
153             }
154             if(dep[x]<dep[y])swap(x,y);
155             ans+=query(1,n,1,idx[y],idx[x]);
156             if(!ans)ans=1;
157             printf("%d\n",ans);
158         }
159     }
160 }

 

以上是关于B20J_2243_[SDOI2011]染色_树链剖分+线段树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2243: [SDOI2011]染色 [树链剖分]

2243: [SDOI2011]染色(树链剖分+线段树)

bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分

bzoj 2243: [SDOI2011]染色 (树链剖分+线段树 区间合并)

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并