首页 > 代码库 > 【BZOJ2243】染色(树链剖分)

【BZOJ2243】染色(树链剖分)

题意:

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

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

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

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

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

思路:树上的路径染色问题可以用树剖解决。

        对于线段树的某个节点我们记录以下信息:最左端颜色,最右端颜色,整段中段数,以及lazytag。

        其中lazytag>=0时表示该区间要改成什么颜色,-1表示当前节点没有标记。

        转换到树上做即可

        BZOJ过了样例就一遍过(萎靡)

  1 type un=record
  2          l,r,s,tag:longint;
  3         end;
  4 var t:array[1..500000]of un;
  5     f:array[1..110000,0..18]of longint;
  6     head,vet,next,flag,dep,fa,top,
  7     tid,id,size,son,a:array[1..210000]of longint;
  8     n,m,i,j,k,x,y,z,q,tot,time:longint;
  9     ch:string;
 10     emp:un;
 11 
 12 procedure swap(var x,y:longint);
 13 var t:longint;
 14 begin
 15  t:=x; x:=y; y:=t;
 16 end;
 17 
 18 procedure add(a,b:longint);
 19 begin
 20  inc(tot);
 21  next[tot]:=head[a];
 22  vet[tot]:=b;
 23  head[a]:=tot;
 24 end;
 25 
 26 procedure dfs1(u:longint);
 27 var e,v,maxsize,i:longint;
 28 begin
 29  flag[u]:=1; size[u]:=1; maxsize:=0; son[u]:=0;
 30  for i:=1 to 18 do
 31  begin
 32   if dep[u]<(1<<i) then break;
 33   f[u,i]:=f[f[u,i-1],i-1];
 34  end;
 35 
 36  e:=head[u];
 37  while e<>0 do
 38  begin
 39   v:=vet[e];
 40   if flag[v]=0 then
 41   begin
 42    dep[v]:=dep[u]+1;
 43    f[v,0]:=u;
 44    fa[v]:=u;
 45    dfs1(v);
 46    size[u]:=size[u]+size[v];
 47    if size[v]>maxsize then
 48    begin
 49     maxsize:=size[v];
 50     son[u]:=v;
 51    end;
 52   end;
 53   e:=next[e];
 54  end;
 55 end;
 56 
 57 procedure dfs2(u,ance:longint);
 58 var e,v:longint;
 59 begin
 60  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
 61  if son[u]>0 then dfs2(son[u],ance);
 62  e:=head[u];
 63  while e<>0 do
 64  begin
 65   v:=vet[e];
 66   if flag[v]=0 then dfs2(v,v);
 67   e:=next[e];
 68  end;
 69 end;
 70 
 71 function lca(x,y:longint):longint;
 72 var i,d:longint;
 73 begin
 74  if dep[x]<dep[y] then swap(x,y);
 75  d:=dep[x]-dep[y];
 76  for i:=0 to 18 do
 77   if d and (1<<i)>0 then x:=f[x,i];
 78  for i:=18 downto 0 do
 79   if f[x,i]<>f[y,i] then
 80   begin
 81    x:=f[x,i]; y:=f[y,i];
 82   end;
 83  if x=y then exit(x);
 84  exit(f[x,0]);
 85 end;
 86 
 87 procedure pushup(p:longint);
 88 begin
 89  t[p].l:=t[p<<1].l; t[p].r:=t[p<<1+1].r;
 90  if t[p<<1].r<>t[p<<1+1].l then t[p].s:=t[p<<1].s+t[p<<1+1].s
 91   else t[p].s:=t[p<<1].s+t[p<<1+1].s-1;
 92 end;
 93 
 94 procedure pushdown(p,l,r:longint);
 95 var tmp:longint;
 96 begin
 97  tmp:=t[p].tag; t[p].tag:=-1;
 98  if (tmp=-1)or(l=r) then exit;
 99  t[p<<1].s:=1; t[p<<1+1].s:=1;
100  t[p<<1].tag:=tmp; t[p<<1+1].tag:=tmp;
101  t[p<<1].l:=tmp; t[p<<1].r:=tmp;
102  t[p<<1+1].l:=tmp; t[p<<1+1].r:=tmp;
103 end;
104 
105 procedure build(l,r,p:longint);
106 var mid:longint;
107 begin
108  if l=r then
109  begin
110   t[p].s:=1;
111   t[p].tag:=-1;
112   exit;
113  end;
114  t[p].tag:=-1;
115  mid:=(l+r)>>1;
116  build(l,mid,p<<1);
117  build(mid+1,r,p<<1+1);
118 end;
119 
120 procedure update(l,r,x,y,v,p:longint);
121 var mid:longint;
122 begin
123  pushdown(p,l,r);
124  if (l>=x)and(r<=y) then
125  begin
126   t[p].l:=v; t[p].r:=v;
127   t[p].s:=1; t[p].tag:=v;
128   exit;
129  end;
130  mid:=(l+r)>>1;
131  if x<=mid then update(l,mid,x,y,v,p<<1);
132  if y>mid then update(mid+1,r,x,y,v,p<<1+1);
133  pushup(p);
134 end;
135 
136 function query(l,r,x,y,p:longint):longint;
137 var mid,t1,t2:longint;
138 begin
139  pushdown(p,l,r);
140  if (l>=x)and(r<=y) then exit(t[p].s);
141  mid:=(l+r)>>1;
142  t1:=0; t2:=0;
143  if x<=mid then t1:=query(l,mid,x,y,p<<1);
144  if y>mid then t2:=query(mid+1,r,x,y,p<<1+1);
145  if t1=0 then exit(t2);
146  if t2=0 then exit(t1);
147  query:=t1+t2;
148  if t[p<<1].r=t[p<<1+1].l then dec(query);
149 end;
150 
151 function get(l,r,x,p:longint):longint;
152 var mid:longint;
153 begin
154  pushdown(p,l,r);
155  if (l=x)and(r=x) then exit(t[p].l);
156  mid:=(l+r)>>1;
157  if x<=mid then exit(get(l,mid,x,p<<1))
158   else exit(get(mid+1,r,x,p<<1+1));
159 end;
160 
161 function ask(x,y:longint):longint;
162 var q:longint;
163 begin
164  q:=lca(x,y);
165  ask:=0;
166  while top[x]<>top[q] do
167  begin
168   ask:=ask+query(1,n,tid[top[x]],tid[x],1);
169   if get(1,n,tid[top[x]],1)=get(1,n,tid[fa[top[x]]],1) then dec(ask);
170   x:=fa[top[x]];
171  end;
172  ask:=ask+query(1,n,tid[q],tid[x],1);
173  while top[y]<>top[q] do
174  begin
175   ask:=ask+query(1,n,tid[top[y]],tid[y],1);
176   if get(1,n,tid[top[y]],1)=get(1,n,tid[fa[top[y]]],1) then dec(ask);
177   y:=fa[top[y]];
178  end;
179  ask:=ask+query(1,n,tid[q],tid[y],1);
180  dec(ask);
181 
182 end;
183 
184 procedure solve(x,y,z:longint);
185 var q:longint;
186 begin
187  q:=lca(x,y);
188  while top[x]<>top[q] do
189  begin
190   update(1,n,tid[top[x]],tid[x],z,1);
191   x:=fa[top[x]];
192  end;
193  update(1,n,tid[q],tid[x],z,1);
194  while top[y]<>top[q] do
195  begin
196   update(1,n,tid[top[y]],tid[y],z,1);
197   y:=fa[top[y]];
198  end;
199  update(1,n,tid[q],tid[y],z,1);
200 end;
201 
202 begin
203  assign(input,bzoj2243.in); reset(input);
204  assign(output,bzoj2243.out); rewrite(output);
205  readln(n,m);
206  for i:=1 to n do read(a[i]);
207  for i:=1 to n-1 do
208  begin
209   readln(x,y);
210   add(x,y);
211   add(y,x);
212  end;
213  dfs1(1);
214  fillchar(flag,sizeof(flag),0);
215  dfs2(1,1);
216  build(1,n,1);
217  for i:=1 to n do update(1,n,tid[i],tid[i],a[i],1);
218  //for i:=1 to n do write(a[id[i]], );
219  for i:=1 to m do
220  begin
221   readln(ch);
222   x:=0; y:=0; z:=0;
223   case ch[1] of
224    C:
225    begin
226     for k:=3 to length(ch) do
227     begin
228      if ch[k]=  then break;
229      x:=x*10+ord(ch[k])-ord(0);
230     end;
231     j:=k+1;
232     for k:=j to length(ch) do
233     begin
234      if ch[k]=  then break;
235      y:=y*10+ord(ch[k])-ord(0);
236     end;
237     j:=k+1;
238     for k:=j to length(ch) do z:=z*10+ord(ch[k])-ord(0);
239     solve(x,y,z);
240    end;
241 
242    Q:
243    begin
244     for k:=3 to length(ch) do
245     begin
246      if ch[k]=  then break;
247      x:=x*10+ord(ch[k])-ord(0);
248     end;
249     j:=k+1;
250     for k:=j to length(ch) do y:=y*10+ord(ch[k])-ord(0);
251     writeln(ask(x,y));
252    end;
253   end;
254  end;
255  close(input);
256  close(output);
257 end.

 

【BZOJ2243】染色(树链剖分)