bzoj4817: [Sdoi2017]树点涂色
4817: [Sdoi2017]树点涂色
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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
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.