[BZOJ3626] [LNOI2014]LCA
2016-02-20 18:12
423 查看
传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=3626题目大意
给定一棵树,询问∑bi=adep[lca(i,c)]\sum_{i=a}^bdep[lca(i,c)]题解
ORZ我们先考虑可以怎么求两个点的lcalca的深度,我们对其中一个到根上的所有点都+1,然后查询另一个点到根的所有点权和即可
然后对于本题的所有询问[L,R][L,R]都可以拆成[1,L−1]和[1,R][1,L-1]和[1,R]这样我们离线把查询排序,依次把11~nn到根路径都+1然后查询即可
const maxn=50005; var w:array[0..3*maxn,1..2]of longint; x:array[0..2*maxn,1..4]of longint; seg:array[0..4*maxn,1..4]of longint; fa,son,size,dep,top,pos:array[0..maxn]of longint; ans:array[0..maxn]of int64; i,j,k:longint; n,m,len,a,b,c,now:longint; procedure swap(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c; end; procedure init(a,b:longint); begin w[len,1]:=b; if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len; w[a,1]:=len; inc(len); end; procedure sort(l,r:longint); var i,j,a,b,c,d:longint; begin i:=l; j:=r; a:=x[(l+r)div 2,1]; b:=x[(l+r)div 2,2]; repeat while (x[i,1]<a)or((x[i,1]=a)and(x[i,2]<b)) do inc(i); while (x[j,1]>a)or((x[j,1]=a)and(x[j,2]>b)) do dec(j); if not(i>j) then begin d:=1; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c; d:=2; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c; d:=3; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c; d:=4; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c; inc(i); dec(j); end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; procedure dfs1(a:longint); var tt,v:longint; begin tt:=w[a,2]; size[a]:=1; v:=0; while tt<>0 do begin if fa[a]<>w[tt,1] then begin fa[w[tt,1]]:=a; dep[w[tt,1]]:=dep[a]+1; dfs1(w[tt,1]); inc(size[a],size[w[tt,1]]); if size[w[tt,1]]>size[v] then v:=w[tt,1]; end; tt:=w[tt,2]; end; son[a]:=v; end; procedure dfs2(a,pre:longint); var tt:longint; begin tt:=w[a,2]; inc(len); pos[a]:=len; top[a]:=pre; if son[a]<>0 then dfs2(son[a],pre); while tt<>0 do begin if (w[tt,1]<>fa[a])and(w[tt,1]<>son[a]) then dfs2(w[tt,1],w[tt,1]); tt:=w[tt,2]; end; end; procedure build(a,l,r:longint); var mid:longint; begin seg[a,1]:=l; seg[a,2]:=r; seg[a,3]:=0; seg[a,4]:=0; if l=r then exit; mid:=(l+r)>>1; build(a<<1,l,mid); build(a<<1+1,mid+1,r); end; procedure pushdown(a:longint); begin if seg[a,1]=seg[a,2] then begin seg[a,4]:=0; exit; end; inc(seg[a<<1,4],seg[a,4]); inc(seg[a<<1,3],seg[a,4]*(seg[a<<1,2]-seg[a<<1,1]+1)); inc(seg[a<<1+1,4],seg[a,4]); inc(seg[a<<1+1,3],seg[a,4]*(seg[a<<1+1,2]-seg[a<<1+1,1]+1)); seg[a,4]:=0; end; procedure update(a,l,r:longint); var mid:longint; begin if seg[a,4]<>0 then pushdown(a); if (l=seg[a,1])and(r=seg[a,2]) then begin inc(seg[a,4]); seg[a,3]:=seg[a,3]+seg[a,2]-seg[a,1]+1; exit; end; mid:=(seg[a,1]+seg[a,2])>>1; if r<=mid then update(a<<1,l,r) else if l>mid then update(a<<1+1,l,r) else begin update(a<<1,l,mid); update(a<<1+1,mid+1,r); end; seg[a,3]:=seg[a<<1,3]+seg[a<<1+1,3]; end; function query(a,l,r:longint):longint; var mid:longint; begin if seg[a,4]<>0 then pushdown(a); if (l=seg[a,1])and(r=seg[a,2]) then exit(seg[a,3]); mid:=(seg[a,1]+seg[a,2])>>1; if r<=mid then exit(query(a<<1,l,r)) else if l>mid then exit(query(a<<1+1,l,r)) else exit(query(a<<1,l,mid)+query(a<<1+1,mid+1,r)); end; procedure change(a,b:longint); begin while top[a]<>top[b] do begin if dep[top[a]]<dep[top[b]] then swap(a,b); update(1,pos[top[a]],pos[a]); a:=fa[top[a]]; end; if dep[a]>dep[b] then swap(a,b); update(1,pos[a],pos[b]); end; function queryans(a,b:longint):int64; var c:longint; ans:int64; begin ans:=0; while top[a]<>top[b] do begin if dep[top[a]]<dep[top[b]] then swap(a,b); c:=query(1,pos[top[a]],pos[a]); inc(ans,c); a:=fa[top[a]]; end; if dep[a]>dep[b] then swap(a,b); c:=query(1,pos[a],pos[b]); inc(ans,c); exit(ans); end; begin readln(n,m); len:=n+1; for i:=2 to n do begin readln(a); inc(a); init(a,i); init(i,a); end; len:=0; for i:=1 to m do begin readln(a,b,c); inc(a); inc(b); inc(c); inc(len); x[len,1]:=a-1; x[len,2]:=c; x[len,3]:=i; x[len,4]:=-1; inc(len); x[len,1]:=b; x[len,2]:=c; x[len,3]:=i; x[len,4]:=1; end; sort(1,len); {x[i,1] x[i,2]} x[0,1]:=len; build(1,1,n); dep[1]:=1; fa[1]:=0; size[0]:=0; dfs1(1); len:=0; dfs2(1,1); now:=0; for i:=1 to x[0,1] do begin for j:=now+1 to x[i,1] do change(1,j); now:=x[i,1]; ans[x[i,3]]:=ans[x[i,3]]+queryans(1,x[i,2])*x[i,4]; end; for i:=1 to m do writeln(ans[i] mod 201314); end.
相关文章推荐
- spring-aop学习笔记
- 多线程
- test
- 测试必备技能系列4:如何用SSH向linux服务器上传下载文件
- java中transient关键字
- 测试必备技能系列4:如何用SSH向linux服务器上传下载文件
- 如何判断js中的数据类型
- STM32的bootloader IAP编程(转载总结)
- LinkedList源码分析
- JavaScript数据类型
- Android 启动Activity的方式
- Android的通讯员——notification
- 2016年本博客知识体系引导(持续更新)
- Git从零教你入门(4):Git服务之 gogs部署安装
- Git从零教你入门(4):Git服务之 gogs部署安装
- 改变系统默认的语言,back改为中文,delete改为中文
- 【POJ】1258 - Agri-Net(克鲁斯塔尔)(水)
- BZOJ3669: [Noi2014]魔法森林
- unity 解析tmx 2
- LVS:三种负载均衡方式比较+另三种负载均衡方式