[BZOJ3531] SDOI2014 树链剖分+动态开点线段树
来源:互联网 发布:金蝶软件数据库安装 编辑:程序博客网 时间:2024/05/29 09:25
首先发现是一棵树,想到树链剖分来维护路径。
但是如何把不同宗教的点分开计数?想到给每一个宗教开一颗线段树来维护,因为总共点数只有10^5个,可以采取动态开点来保证内存不超。
代码
type xtree=^xtreenode; xtreenode=record max,sum,l,r:longint; ls,rs:xtree; end; edge=^edgenode; edgenode=record t:longint; next:edge; end;var n,q,i,j,u,v,time,ans,ck,x,y:longint; c1:char; w,c,dfn,fdfn,deep,size,head,hs,fa:array[0..100100]of longint; con:array[1..100100]of edge; xtr:array[1..100100]of xtree;procedure ins(x,y:longint);var p:edge;begin new(p); p^.t:=y; p^.next:=con[x]; con[x]:=p;end;function maxx(x,y:longint):longint;begin if x>y then exit(x) else exit(y);end;procedure outp(x:xtree);begin if x=nil then exit; writeln(x^.l,' ',x^.r,' ',x^.max,' ',x^.sum); outp(x^.ls); outp(x^.rs);end;procedure dfs1(v:longint);var p:edge; max,maxi:longint;begin size[v]:=1; deep[v]:=deep[fa[v]]+1; p:=con[v]; max:=0; maxi:=0; while p<>nil do begin if p^.t<>fa[v] then begin fa[p^.t]:=v; dfs1(p^.t); if size[p^.t]>max then begin max:=size[p^.t]; maxi:=p^.t end; size[v]:=size[v]+size[p^.t]; end; p:=p^.next; end; hs[v]:=maxi;end;procedure dfs2(v:longint);var p:edge;begin inc(time); dfn[v]:=time; fdfn[time]:=v; if hs[fa[v]]=v then head[v]:=head[fa[v]] else head[v]:=v; p:=con[v]; if hs[v]>0 then dfs2(hs[v]); while p<>nil do begin if (p^.t<>fa[v])and(p^.t<>hs[v]) then dfs2(p^.t); p:=p^.next; end;end;procedure build(var x:xtree;sum,max,l,r:longint);begin new(x); x^.l:=l; x^.r:=r; x^.max:=max; x^.sum:=sum; x^.ls:=nil; x^.rs:=nil;end;procedure updata(var x:xtree);begin x^.sum:=0; x^.max:=0; if x^.ls<>nil then begin x^.sum:=x^.ls^.sum; x^.max:=x^.ls^.max; end; if x^.rs<>nil then begin x^.sum:=x^.sum+x^.rs^.sum; x^.max:=maxx(x^.max,x^.rs^.max) ; end;end;procedure change(var x:xtree;v,nw,l,r:longint);var mid:longint;begin if x=nil then build(x,0,0,l,r); if l=r then begin x^.max:=nw; x^.sum:=nw; exit; end; mid:=(l+r) div 2; if (v>=l)and(v<=mid) then change(x^.ls,v,nw,l,mid) else change(x^.rs,v,nw,mid+1,r); updata(x);end;procedure dele(var x:xtree;v,nw,l,r:longint);var mid:longint;begin if l=r then begin x:=nil; exit; end; mid:=(l+r) div 2; if (v>=l)and(v<=mid) then dele(x^.ls,v,nw,l,mid) else dele(x^.rs,v,nw,mid+1,r); updata(x); if x^.sum=0 then begin x:=nil; exit; end;end;function qsum(x:xtree;l,r:longint):longint;var mid:longint;begin if x=nil then exit(0); if (l=x^.l)and(r=x^.r) then exit(x^.sum); mid:=(x^.l+x^.r)div 2; if r<=mid then exit(qsum(x^.ls,l,r)); if l>mid then exit(qsum(x^.rs,l,r)); exit(qsum(x^.ls,l,mid)+qsum(x^.rs,mid+1,r));end;function qmax(x:xtree;l,r:longint):longint;var mid:longint;begin if x=nil then exit(0); if (l=x^.l)and(r=x^.r) then exit(x^.max); mid:=(x^.l+x^.r)div 2; if r<=mid then exit(qmax(x^.ls,l,r)); if l>mid then exit(qmax(x^.rs,l,r)); exit(maxx(qmax(x^.ls,l,mid),qmax(x^.rs,mid+1,r)));end;begin readln(n,q); for i:=1 to n do readln(w[i],c[i]); for i:=1 to n-1 do begin readln(u,v); ins(u,v); ins(v,u); end; dfs1(1); dfs2(1); for i:=1 to n do change(xtr[c[i]],dfn[i],w[i],1,n); for i:=1 to q do begin {for j:=1 to 3 do begin outp(xtr[j]); writeln; end; } ans:=0; read(c1);read(c1); readln(x,y); ck:=c[x]; case c1 of 'C':begin dele(xtr[c[x]],dfn[x],w[x],1,n); c[x]:=y; change(xtr[y],dfn[x],w[x],1,n) end; 'W':begin w[x]:=y; change(xtr[c[x]],dfn[x],y,1,n) end; 'S': begin while head[x]<>head[y] do begin if deep[head[x]]>deep[head[y]] then begin ans:=ans+qsum(xtr[ck],dfn[head[x]],dfn[x]); x:=fa[head[x]]; end else begin ans:=ans+qsum(xtr[ck],dfn[head[y]],dfn[y]); y:=fa[head[y]]; end; end; if deep[x]<=deep[y] then ans:=ans+qsum(xtr[ck],dfn[x],dfn[y]) else ans:=ans+qsum(xtr[ck],dfn[y],dfn[x]); writeln(ans); end; 'M': begin while head[x]<>head[y] do begin if deep[head[x]]>deep[head[y]] then begin ans:=maxx(ans,qmax(xtr[ck],dfn[head[x]],dfn[x])); x:=fa[head[x]]; end else begin ans:=maxx(ans,qmax(xtr[ck],dfn[head[y]],dfn[y])); y:=fa[head[y]]; end; end; if deep[x]<=deep[y] then ans:=maxx(ans,qmax(xtr[ck],dfn[x],dfn[y])) else ans:=maxx(ans,qmax(xtr[ck],dfn[y],dfn[x])); writeln(ans); end; end; end;end.
0 0
- Bzoj3531:[Sdoi2014]旅行:树链剖分+动态开点线段树
- [BZOJ3531] SDOI2014 树链剖分+动态开点线段树
- bzoj3531 [Sdoi2014]旅行(树链剖分+动态开点线段树)
- bzoj3531(树链剖分+动态开点线段树)
- 【BZOJ3531】旅行,树链剖分+开点线段树
- |BZOJ 3531|树链剖分|动态开点线段树|[Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行 树链剖分+动态开线段树
- bzoj3531 [Sdoi2014]旅行 【树链剖分+线段树动态开点】
- BZOJ 3531: [Sdoi2014]旅行【树剖+动态开点线段树【听说有人写平衡树?【滑稽
- [BZOJ3531][SDOI2014]旅行(链剖+线段树动态开点)
- 【bzoj3531】[Sdoi2014]旅行 动态开点的线段树
- bzoj3531 [Sdoi2014]旅行 树链剖分 线段树
- 【BZOJ3531】【Sdoi2014】旅行 树链剖分。
- [bzoj3531][Sdoi2014]旅行 树链剖分
- BZOJ-3531 旅行 树链剖分+动态开点线段树
- NOIP2017d2t3 列队 动态开点线段树
- poj2528(动态开点线段树——过不了)
- 动态开点线段树(Radio stations,762E)
- 【VHDL】基本组合电路的设计
- ZCMU—1889
- hdu 2030 汉字统计
- PAT 1097-Deduplication on a Linked List (25)
- 嵌套类、局部类
- [BZOJ3531] SDOI2014 树链剖分+动态开点线段树
- BroadCastReceiver无法接收到广播的一种可能
- 【Codeforces-402B】-Weird Rounding(数学,思维)
- 初学集合框架的几点总结
- 海量数据处理问题之Bit-Map详解
- 黑车司机发车神器(JAVA)
- POJ 3196 Babylonian Roulette G++
- HRBUST
- gets和fgets的区别