BZOJ 2243 [SDOI2011]染色:树剖【维护路径上颜色段】

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

题意:

  给定一棵有n个节点的无根树和m个操作,操作有2类:

  1、将节点a到节点b路径上所有点都染成颜色c;

  2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如"112221"由3段组成:"11"、"222"和"1"。

  请你写一个程序依次完成这m个操作。

 

题解:

  树剖。

  线段树上维护区间颜色段,每个节点:

    dat[]:当前区间的颜色段数量

    st[]:修改标记

    lc[] and rc[]:当前区间的最左端和最右端颜色

    lson[] and rson[]:左右儿子编号

  线段树部分见NOI 2007 项链工厂。

 

  树剖query中,每次a = par[tp[a]]往上跳之前,先判断getcol(dfsx[tp[a]]) == getcol(dfsx[par[tp[a]]])

  如果相等,上下两端合并,sum--。

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <vector>
  5 #define MAX_N 1000005
  6 
  7 using namespace std;
  8 
  9 int n,m;
 10 int tot=0;
 11 int cnt=0;
 12 int c[MAX_N];
 13 int dat[MAX_N];
 14 int st[MAX_N];
 15 int lc[MAX_N];
 16 int rc[MAX_N];
 17 int lson[MAX_N];
 18 int rson[MAX_N];
 19 int par[MAX_N];
 20 int dep[MAX_N];
 21 int siz[MAX_N];
 22 int tp[MAX_N];
 23 int son[MAX_N];
 24 int dfsx[MAX_N];
 25 int idx[MAX_N];
 26 vector<int> edge[MAX_N];
 27 
 28 void read()
 29 {
 30     scanf("%d%d",&n,&m);
 31     for(int i=1;i<=n;i++)
 32     {
 33         scanf("%d",&c[i]);
 34     }
 35     int a,b;
 36     for(int i=1;i<n;i++)
 37     {
 38         scanf("%d%d",&a,&b);
 39         edge[a].push_back(b);
 40         edge[b].push_back(a);
 41     }
 42 }
 43 
 44 void push_down(int now)
 45 {
 46     if(st[now]!=-1)
 47     {
 48         dat[lson[now]]=dat[rson[now]]=1;
 49         st[lson[now]]=st[rson[now]]=st[now];
 50         lc[lson[now]]=rc[lson[now]]=lc[rson[now]]=rc[rson[now]]=st[now];
 51         st[now]=-1;
 52     }
 53 }
 54 
 55 void push_up(int now)
 56 {
 57     dat[now]=0;
 58     lc[now]=lc[lson[now]];
 59     rc[now]=rc[rson[now]];
 60     if(lson[now]) dat[now]+=dat[lson[now]];
 61     if(rson[now]) dat[now]+=dat[rson[now]];
 62     if(lson[now] && rson[now] && rc[lson[now]]==lc[rson[now]]) dat[now]--;
 63 }
 64 
 65 int build(int l,int r)
 66 {
 67     int rt=++tot;
 68     dat[rt]=1;
 69     st[rt]=-1;
 70     lc[rt]=c[idx[l]];
 71     rc[rt]=c[idx[r]];
 72     lson[rt]=rson[rt]=0;
 73     if(l<r)
 74     {
 75         int mid=(l+r)>>1;
 76         lson[rt]=build(l,mid);
 77         rson[rt]=build(mid+1,r);
 78         push_up(rt);
 79     }
 80     return rt;
 81 }
 82 
 83 void update(int a,int b,int k,int l,int r,int x)
 84 {
 85     if(a<=l && r<=b)
 86     {
 87         dat[k]=1;
 88         st[k]=lc[k]=rc[k]=x;
 89         return;
 90     }
 91     if(r<a || b<l) return;
 92     push_down(k);
 93     int mid=(l+r)>>1;
 94     update(a,b,lson[k],l,mid,x);
 95     update(a,b,rson[k],mid+1,r,x);
 96     push_up(k);
 97 }
 98 
 99 int query(int a,int b,int k,int l,int r)
100 {
101     if(a<=l && r<=b) return dat[k];
102     if(r<a || b<l) return 0;
103     push_down(k);
104     int mid=(l+r)>>1;
105     int ans=0;
106     if(a<=mid) ans+=query(a,b,lson[k],l,mid);
107     if(b>mid) ans+=query(a,b,rson[k],mid+1,r);
108     if(a<=mid && b>mid && rc[lson[k]]==lc[rson[k]]) ans--;
109     return ans;
110 }
111 
112 int getcol(int p,int k,int l,int r)
113 {
114     if(l==r) return lc[k];
115     push_down(k);
116     int mid=(l+r)>>1;
117     if(p<=mid) return getcol(p,lson[k],l,mid);
118     else return getcol(p,rson[k],mid+1,r);
119 }
120 
121 void dfs1(int now,int p,int d)
122 {
123     par[now]=p;
124     dep[now]=d;
125     siz[now]=1;
126     for(int i=0;i<edge[now].size();i++)
127     {
128         int temp=edge[now][i];
129         if(temp!=p)
130         {
131             dfs1(temp,now,d+1);
132             siz[now]+=siz[temp];
133         }
134     }
135 }
136 
137 void dfs2(int now,int anc)
138 {
139     tp[now]=anc;
140     son[now]=-1;
141     cnt++;
142     idx[cnt]=now;
143     dfsx[now]=cnt;
144     for(int i=0;i<edge[now].size();i++)
145     {
146         int temp=edge[now][i];
147         if((son[now]==-1 || siz[temp]>siz[son[now]]) && temp!=par[now])
148         {
149             son[now]=temp;
150         }
151     }
152     if(son[now]!=-1) dfs2(son[now],anc);
153     for(int i=0;i<edge[now].size();i++)
154     {
155         int temp=edge[now][i];
156         if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp);
157     }
158 }
159 
160 void update_chain(int a,int b,int x)
161 {
162     while(tp[a]!=tp[b])
163     {
164         if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
165         update(dfsx[tp[a]],dfsx[a],1,1,n,x);
166         a=par[tp[a]];
167     }
168     if(dep[a]<dep[b]) swap(a,b);
169     update(dfsx[b],dfsx[a],1,1,n,x);
170 }
171 
172 int query_chain(int a,int b)
173 {
174     int sum=0;
175     while(tp[a]!=tp[b])
176     {
177         if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
178         sum+=query(dfsx[tp[a]],dfsx[a],1,1,n);
179         if(getcol(dfsx[tp[a]],1,1,n)==getcol(dfsx[par[tp[a]]],1,1,n)) sum--;
180         a=par[tp[a]];
181     }
182     if(dep[a]<dep[b]) swap(a,b);
183     sum+=query(dfsx[b],dfsx[a],1,1,n);
184     return sum;
185 }
186 
187 void work()
188 {
189     dfs1(1,-1,0);
190     dfs2(1,1);
191     build(1,n);
192     char s[16];
193     int a,b,c;
194     while(m--)
195     {
196         scanf("%s",s);
197         if(s[0]=='Q')
198         {
199             scanf("%d%d",&a,&b);
200             printf("%d\n",query_chain(a,b));
201         }
202         else
203         {
204             scanf("%d%d%d",&a,&b,&c);
205             update_chain(a,b,c);
206         }
207     }
208 }
209 
210 int main()
211 {
212     read();
213     work();
214 }

 

posted @ 2017-12-01 16:13  Leohh  阅读(338)  评论(0编辑  收藏  举报