bzoj4817: [Sdoi2017]树点涂色

4817: [Sdoi2017]树点涂色

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 435  Solved: 250
[Submit][Status][Discuss]

Description

Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
1 x:
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
2 x y:
求x到y的路径的权值。
3 x y:
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行m次操作
 

Input

第一行两个数n,m。
接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
接下来m行,表示操作,格式见题目描述
1<=n,m<=100000
 

Output

每当出现2,3操作,输出一行。
如果是2操作,输出一个数表示路径的权值
如果是3操作,输出一个数表示权值的最大值
 

Sample Input

5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5

Sample Output

3
4
2
2

题解

  我们用实边代表边两端颜色相同,虚边代表两端颜色不同,1操作就是一次access的过程。

  在dfs序上,我们用线段树维护每个点到根路径上的虚边数目,一开始每个点的值都是自己的深度。每次access虚实边转换的时候,我们就把由实变虚的边整个子树的值+1,由虚变实的边整个子树的值-1。

  2操作就是u的值+v的值-2*lca(u,v)的值+1。

  3操作就是区间求max

  1 program j01;
  2 const maxn=100086;
  3 var t:array[0..maxn]of record son:array[0..1]of longint;fa:longint; end;
  4     f:array[0..4*maxn]of record tag,mx:longint; end;
  5     st:array[0..20,0..2*maxn]of longint;
  6     dep,home,dfn,ed,id,fir:array[0..maxn]of longint;
  7     q,next,bin:array[0..2*maxn]of longint;
  8     head:array[0..maxn]of longint;
  9     u,v,op,n,m,i,tt,tot,time,lc:longint;
 10     ll,rr,dd:longint;
 11     
 12 procedure swap(var a,b:longint);inline;var c:longint;begin c:=a;a:=b;b:=c; end;
 13 function max(a,b:longint):longint;inline;begin if a>b then exit(a) else exit(b); end;
 14 procedure addd(var h:longint;v:longint);inline;begin inc(tt);q[tt]:=v;next[tt]:=h;h:=tt; end;
 15 
 16 procedure dfs(i:longint);
 17 var j:longint;
 18 begin
 19     inc(tot);dfn[i]:=tot;id[tot]:=i;
 20     inc(time);st[0,time]:=i;fir[i]:=time;
 21     j:=head[i];
 22     while j>0 do
 23     begin
 24         if(q[j]<>t[i].fa)then
 25         begin
 26             dep[q[j]]:=dep[i]+1;t[q[j]].fa:=i;
 27             dfs(q[j]);inc(time);st[0,time]:=i;
 28         end;
 29         j:=next[j];
 30     end;
 31     ed[i]:=tot;
 32 end;
 33 {segement tree-------------------------------------------------------}
 34 
 35 procedure build(i,l,r:longint);
 36 var mid:longint;
 37 begin
 38     f[i].tag:=0;if l=r then begin f[i].mx:=dep[id[l]]; exit; end;
 39     mid:=(l+r)div 2;build(i*2,l,mid);build(i*2+1,mid+1,r);f[i].mx:=max(f[i*2].mx,f[i*2+1].mx);
 40 end;
 41 
 42 procedure pushdown(i:longint);
 43 var tag:longint;
 44 begin
 45     if f[i].tag=0 then exit;tag:=f[i].tag;f[i].tag:=0;
 46     inc(f[i*2].tag,tag);inc(f[i*2].mx,tag);
 47     inc(f[i*2+1].tag,tag);inc(f[i*2+1].mx,tag);
 48 end;
 49 
 50 procedure change(i,l,r:longint);
 51 var mid:longint;
 52 begin
 53     if(ll<=l)and(r<=rr)then begin inc(f[i].tag,dd);inc(f[i].mx,dd);exit; end;
 54     mid:=(l+r)div 2;pushdown(i);
 55     if ll<=mid then change(i*2,l,mid);
 56     if mid+1<=rr then change(i*2+1,mid+1,r);
 57     f[i].mx:=max(f[i*2].mx,f[i*2+1].mx);
 58 end;
 59 
 60 function find(i,l,r,ps:longint):longint;
 61 var mid:longint;
 62 begin
 63     if l=r then exit(f[i].mx);
 64     mid:=(l+r)div 2;pushdown(i);
 65     if ps<=mid then exit(find(i*2,l,mid,ps)) else exit(find(i*2+1,mid+1,r,ps));
 66 end;
 67 
 68 function ask(i,l,r:longint):longint;
 69 var mid,res:longint;
 70 begin
 71     if(ll<=l)and(r<=rr)then exit(f[i].mx);
 72     mid:=(l+r)div 2;pushdown(i);res:=0;
 73     if ll<=mid then res:=max(res,ask(i*2,l,mid));
 74     if mid+1<=rr then res:=max(res,ask(i*2+1,mid+1,r));
 75     exit(res);
 76 end;
 77 
 78 {segment tree--------------------------------------------------------}
 79 
 80 {st_lca--------------------------------------------------------------}
 81 
 82 function min_st(a,b:longint):longint;inline;begin if dep[a]<dep[b] then exit(a) else exit(b); end;
 83 
 84 procedure getst;
 85 var i,j:longint;
 86 begin
 87     bin[1]:=0;
 88     for i:=2 to time do
 89         if i and(i-1)=0 then bin[i]:=bin[i-1]+1 else bin[i]:=bin[i-1];
 90     for i:=1 to bin[time] do
 91         for j:=1 to time+1-(1 shl i) do 
 92             st[i,j]:=min_st(st[i-1,j],st[i-1,j+(1 shl (i-1))]);
 93 end;
 94 
 95 function lca(u,v:longint):longint;
 96 var k:longint;
 97 begin
 98     u:=fir[u];v:=fir[v];
 99     if u>v then swap(u,v);k:=bin[v-u+1];
100     exit(min_st(st[k,u],st[k,v+1-(1 shl k)]));
101 end;
102 
103 {st_lca--------------------------------------------------------------}
104 
105 {lct-----------------------------------------------------------------}
106 
107 function isroot(i:longint):boolean;inline;begin exit((t[t[i].fa].son[0]<>i)and(t[t[i].fa].son[1]<>i));end;
108 
109 procedure rotate(i,dd:longint);
110 var k,l:longint;
111 begin
112     k:=t[i].son[dd];l:=t[i].fa;
113     if not isroot(i) then t[l].son[ord(t[l].son[1]=i)]:=k;t[k].fa:=l;
114     t[i].son[dd]:=t[k].son[1-dd];t[t[k].son[1-dd]].fa:=i;
115     t[k].son[1-dd]:=i;t[i].fa:=k;
116 end;
117 
118 procedure splay(i:longint);
119 var p,dd:longint;
120 begin
121     while not isroot(i) do
122     begin
123         p:=t[i].fa;
124         if isroot(p) then begin rotate(p,ord(t[p].son[1]=i));break; end;
125         dd:=ord(t[t[p].fa].son[1]=p);
126         if t[p].son[dd]=i then rotate(t[p].fa,dd) else rotate(t[i].fa,1-dd);
127         rotate(t[i].fa,dd);
128     end;
129 end;
130 
131 function findmn(i:longint):longint;
132 begin
133     if i=0 then exit(0);
134     while t[i].son[0]>0 do i:=t[i].son[0];exit(i);
135 end;
136 
137 procedure access(x:longint);
138 var y,u:longint;
139 begin
140     y:=0;
141     while x>0 do
142     begin
143         splay(x);u:=findmn(t[x].son[1]);
144         if u>0 then begin ll:=dfn[u];rr:=ed[u];dd:=1;change(1,1,n); end;
145         t[x].son[1]:=y;u:=findmn(y);
146         if u>0 then begin ll:=dfn[u];rr:=ed[u];dd:=-1;change(1,1,n); end;
147         y:=x;x:=t[x].fa;
148     end;
149 end;
150 
151 {lct-----------------------------------------------------------------}
152     
153 begin
154     assign(input,'1.in');reset(input);
155     readln(n,m);
156     fillchar(head,sizeof(head),0);tt:=0;
157     for i:=1 to n-1 do
158     begin
159         readln(u,v);addd(head[u],v);addd(head[v],u);
160     end;
161     dep[1]:=0;t[1].fa:=0;time:=0;tot:=0;dfs(1);
162     build(1,1,n);getst;
163     for i:=1 to m do
164     begin
165         read(op);
166         if op=1 then
167         begin
168             readln(u);access(u);
169         end;
170         if op=2 then
171         begin
172             readln(u,v);lc:=lca(u,v);
173             writeln(find(1,1,n,dfn[u])+find(1,1,n,dfn[v])-2*find(1,1,n,dfn[lc])+1);
174         end;
175         if op=3 then
176         begin
177             readln(u);ll:=dfn[u];rr:=ed[u];
178             writeln(ask(1,1,n)+1);
179         end;
180     end;
181     close(input);
182 end.
View Code
原文地址:https://www.cnblogs.com/oldjang/p/7000035.html