[BZOJ3991] [SDOI2015]寻宝游戏
2016-03-06 13:57
260 查看
传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=3991题目大意
给定一棵树,询问从某一关键点出发再回到该点遍历所有关键点的最短距离支持加入1个和删除1个关键点
题解
首先最短路径一定是按照DFS序走所以就动态维护关键点的DFS序就好了
(c++能用set!!我只好写了个SplayQAQAQAQ)
{$M 100000000,0,100000000} const maxn=100050; inf=100000000000000; var w:array[0..3*maxn,1..3]of longint; dd,pos,vis:array[-1..maxn]of longint; dep:array[-1..maxn]of int64; son:array[-1..maxn,1..2]of longint; fa,val:array[-1..maxn]of longint; st:array[0..maxn,0..20]of longint; i,j,k:longint; n,m,len,a,b,c,root:longint; ans:int64; procedure init(a,b,c:longint); begin w[len,1]:=b; w[len,2]:=c; w[len,3]:=0; if (w[a,3]=0) then w[a,3]:=len else w[w[a,1],3]:=len; w[a,1]:=len; inc(len); end; procedure dfs(a,fa:longint); var tt:longint; begin tt:=w[a,3]; inc(len); pos[a]:=len; while (tt<>0) do begin if (w[tt,1]<>fa) then begin dep[w[tt,1]]:=dep[a]+int64(w[tt,2]); dd[w[tt,1]]:=dd[a]+1; st[w[tt,1],0]:=a; dfs(w[tt,1],a); end; tt:=w[tt,3]; end; end; function lca(a,b:longint):longint; var i:longint; begin if (dd[a]<dd[b]) then begin i:=a; a:=b; b:=i; end; for i:=20 downto 0 do if (dd[st[a,i]]>=dd[b]) then a:=st[a,i]; if (a=b) then exit(a); for i:=20 downto 0 do if (st[a,i]<>st[b,i]) then begin a:=st[a,i]; b:=st[b,i]; end; exit(st[a,0]); end; function dis(a,b:longint):int64; begin exit(dep[a]+dep[b]-2*dep[lca(a,b)]); end; procedure rotate(a,kind:longint); var b,c,unkind:longint; begin b:=fa[a]; c:=fa[b]; unkind:=kind xor 3; fa[son[a,unkind]]:=b; fa[b]:=a; son[b,kind]:=son[a,unkind]; son[a,unkind]:=b; fa[a]:=c; if (son[c,1]=b) then son[c,1]:=a else son[c,2]:=a; end; procedure splay(a,goal:longint); var kind,unkind,b:longint; begin while (fa[a]<>goal) do begin b:=fa[a]; if (son[b,1]=a) then kind:=1 else kind:=2; unkind:=kind xor 3; if (fa[b]=goal) then rotate(a,kind) else if (son[fa[b],kind]=b) then begin rotate(b,kind); rotate(a,kind); end else begin rotate(a,kind); rotate(a,unkind); end; end; if (goal=-1) then root:=a; end; procedure insert(a:longint); var tt,fath,kind:longint; begin tt:=root; while (tt<>-1) do if (pos[a]<pos[val[tt]]) then begin fath:=tt; kind:=1; tt:=son[tt,1]; end else begin fath:=tt; kind:=2; tt:=son[tt,2]; end; inc(len); son[len,1]:=-1; son[len,2]:=-1; fa[len]:=fath; val[len]:=a; son[fath,kind]:=len; splay(len,-1); end; procedure delete(a:longint); var tt:longint; begin tt:=root; while (val[tt]<>a) do if (pos[a]<pos[val[tt]]) then tt:=son[tt,1] else tt:=son[tt,2]; splay(tt,-1); tt:=son[root,1]; while (son[tt,2]<>-1) do tt:=son[tt,2]; splay(tt,root); son[tt,2]:=son[root,2]; root:=tt; fa[son[root,2]]:=tt; fa[root]:=-1; end; function getpre(a:longint):longint; var tt:longint; begin tt:=root; while (val[tt]<>a) do if (pos[a]<pos[val[tt]]) then tt:=son[tt,1] else tt:=son[tt,2]; splay(tt,-1); splay(1,root); if (son[1,2]=-1) then begin splay(2,-1); splay(1,root); end; tt:=son[son[root,1],2]; while (son[tt,2]<>-1) do tt:=son[tt,2]; exit(val[tt]); end; function getsuf(a:longint):longint; var tt:longint; begin tt:=root; while (val[tt]<>a) do if (pos[a]<pos[val[tt]]) then tt:=son[tt,1] else tt:=son[tt,2]; splay(tt,-1); splay(2,root); if (son[2,1]=-1) then begin splay(1,-1); splay(2,root); end; tt:=son[son[root,2],1]; while (son[tt,1]<>-1) do tt:=son[tt,1]; exit(val[tt]); end; begin readln(n,m); len:=n+1; for i:=1 to n-1 do begin readln(a,b,c); init(a,b,c); init(b,a,c); end; dep[1]:=1; dd[1]:=1; st[1,0]:=0; len:=0; dfs(1,0); for j:=1 to 20 do for i:=1 to n do st[i,j]:=st[st[i,j-1],j-1]; fillchar(vis,sizeof(vis),0); ans:=0; pos[-1]:=-maxlongint; pos[maxn]:=maxlongint; len:=2; root:=1; son[1,1]:=-1; son[1,2]:=2; fa[1]:=-1; val[1]:=-1; son[2,1]:=-1; son[2,2]:=-1; fa[2]:=1; val[2]:=maxn; for i:=1 to m do begin readln(a); if (vis[a]=0) then begin vis[a]:=1; insert(a); b:=getpre(a); c:=getsuf(a); ans:=ans-dis(b,c)+dis(a,b)+dis(a,c); end else begin vis[a]:=0; b:=getpre(a); c:=getsuf(a); ans:=ans-dis(a,b)-dis(a,c)+dis(b,c); delete(a); end; writeln(ans); end; end.
相关文章推荐
- <android编译ffmpeg+x264+faac> <Android/NDK环境下FFmpeg及AAC,MP3,X264的编译>
- Ubuntu14.04下,GO语言的安装!
- hdu 5120 Intersection(求相交环面积)
- Ubuntu14.04下,GO语言的安装!
- 学习进度第一周
- 面向对象2
- 最近一周工作总结
- 将数组中的数循环移动k位
- 面向对象
- NBUT 1655-木块拼接【模拟】
- C语言格式化说明符
- week2--操作系统是如何工作的
- hdu 5122 K.Bro Sorting(单调栈)
- HDOJ 1045 Fire Net(DFS)
- 主席树的应用
- 关于srand()rand()的用法
- javascript实现网页定时跳转代码
- win7下ubuntu的安装(双系统)
- Android简易版天气预报app的现实(2)
- DOM,SAX,JDOM,DOM4J 四种方式解析xml