bzoj3083 3306
2015-01-16 22:42
190 查看
又见bzoj的语言歧视,囧……
bzoj3083过了本地的数据在上面出现各种奇葩的TLE
835083 phile 3083 Time_Limit_Exceed 17092 kb 4872 ms Pascal/Edit 4931B 2015-01-11 19:53:32
10s的时限在逗我?
UPD:现在已经没有问题了……
这两道题目还是不错的
首先这道题是很像动态树的题目,我们发现树的形态不发生变化,而只是根在变化
考虑树链剖分,修改显然跟根的变化毫无关系
主要是查询,首先对于子树的查询肯定是dfs序(而轻重链剖分正是dfs序的一种特殊形式)
下面我们想,一次换跟操作对哪些点的查询会产生影响
画图可知,换根只会影响新根的祖先们的查询,如果不是祖先,那直接查询即可
而是祖先的话,设查询点x和新根路径上离x最近的那个点为y
显然,除去在原图上以y为根的子树,其余部分都应该是换根后的x的子树
由此题目得解,这里给出bzoj3083的代码
View Code
bzoj3083过了本地的数据在上面出现各种奇葩的TLE
835083 phile 3083 Time_Limit_Exceed 17092 kb 4872 ms Pascal/Edit 4931B 2015-01-11 19:53:32
10s的时限在逗我?
UPD:现在已经没有问题了……
这两道题目还是不错的
首先这道题是很像动态树的题目,我们发现树的形态不发生变化,而只是根在变化
考虑树链剖分,修改显然跟根的变化毫无关系
主要是查询,首先对于子树的查询肯定是dfs序(而轻重链剖分正是dfs序的一种特殊形式)
下面我们想,一次换跟操作对哪些点的查询会产生影响
画图可知,换根只会影响新根的祖先们的查询,如果不是祖先,那直接查询即可
而是祖先的话,设查询点x和新根路径上离x最近的那个点为y
显然,除去在原图上以y为根的子树,其余部分都应该是换根后的x的子树
由此题目得解,这里给出bzoj3083的代码
const inf=2147483647; type node=record po,next:longint; end; var c,e,b,a,d,p,size,top,fa:array[0..100010] of longint; w:array[0..200010] of node; tree,lazy:array[0..100010*4] of longint; anc:array[0..100010,0..17] of longint; root,ch,i,s,len,n,m,x,y,z:longint; function min(a,b:longint):longint; begin if a>b then exit(b) else exit(a); end; procedure push(i:longint); begin lazy[i*2]:=lazy[i]; lazy[i*2+1]:=lazy[i]; tree[i*2]:=lazy[i]; tree[i*2+1]:=lazy[i]; lazy[i]:=0; end; procedure swap(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c; end; procedure add(x,y:longint); begin inc(len); w[len].po:=y; w[len].next:=p[x]; p[x]:=len; end; procedure dfs1(x:longint); var i,y:longint; begin for i:=1 to s do begin y:=anc[x,i-1]; if anc[y,i-1]=0 then break; anc[x,i]:=anc[y,i-1]; end; size[x]:=1; i:=p[x]; while i<>0 do begin y:=w[i].po; if fa[x]<>y then begin d[y]:=d[x]+1; fa[y]:=x; anc[y,0]:=x; dfs1(y); size[x]:=size[x]+size[y]; end; i:=w[i].next; end; end; procedure dfs2(x:longint); var q,i,y:longint; begin inc(len); b[len]:=x; c[x]:=len; q:=0; i:=p[x]; while i<>0 do begin y:=w[i].po; if fa[y]=x then if size[y]>size[q] then q:=y; i:=w[i].next; end; if q<>0 then begin top[q]:=top[x]; dfs2(q); end; i:=p[x]; while i<>0 do begin y:=w[i].po; if (fa[y]=x) and (y<>q) then begin top[y]:=y; dfs2(y); end; i:=w[i].next; end; e[x]:=len; //【c[x],e[x]】表示了以x根的子树所代表的区间 end; procedure build(i,l,r:longint); var m:longint; begin if l=r then tree[i]:=a[b[l]] else begin m:=(l+r) shr 1; build(i*2,l,m); build(i*2+1,m+1,r); tree[i]:=min(tree[i*2],tree[i*2+1]); end; end; procedure change(i,l,r,x,y:longint); var m:longint; begin if (x<=l) and (y>=r) then begin lazy[i]:=z; tree[i]:=z; end else begin if lazy[i]<>0 then push(i); m:=(l+r) shr 1; if x<=m then change(i*2,l,m,x,y); if y>m then change(i*2+1,m+1,r,x,y); tree[i]:=min(tree[i*2],tree[i*2+1]); end; end; procedure work(x,y:longint); var f1,f2:longint; begin f1:=top[x]; f2:=top[y]; while f1<>f2 do begin if d[f1]>=d[f2] then begin change(1,1,n,c[f1],c[x]); x:=fa[f1]; end else begin change(1,1,n,c[f2],c[y]); y:=fa[f2]; end; f1:=top[x]; f2:=top[y]; end; if c[x]>c[y] then swap(x,y); change(1,1,n,c[x],c[y]); end; function getans(i,l,r,x,y:longint):longint; var m,s:longint; begin if x>y then exit(inf); if (x<=l) and (y>=r) then exit(tree[i]) else begin if lazy[i]<>0 then push(i); m:=(l+r) shr 1; s:=inf; if x<=m then s:=getans(i*2,l,m,x,y); if y>m then s:=min(s,getans(i*2+1,m+1,r,x,y)); exit(s); end; end; function check(x,y:longint):boolean; var i,k:longint; begin if d[y]>=d[x] then exit(false); for i:=s downto 0 do if d[x]-1 shl i>=d[y] then x:=anc[x,i]; if x=y then exit(true) else exit(false); end; function ask(x:longint):longint; var a,z,i:longint; begin if x=root then exit(tree[1]); if not check(root,x) then exit(getans(1,1,n,c[x],e[x])) else begin z:=root; for i:=s downto 0 do if d[z]-1 shl i>d[x] then z:=anc[z,i]; //找最近点 a:=min(getans(1,1,n,1,c[z]-1),getans(1,1,n,e[z]+1,n)); exit(a); end; end; begin readln(n,m); for i:=1 to n-1 do begin readln(x,y); add(x,y); add(y,x); end; s:=trunc(ln(n)/ln(2)); for i:=1 to n do read(a[i]); readln(root); dfs1(root); top[root]:=root; len:=0; dfs2(root); build(1,1,n); for i:=1 to m do begin read(ch); if ch=1 then begin readln(x); root:=x; end else if ch=2 then begin readln(x,y,z); work(x,y); end else begin readln(x); writeln(ask(x)); end; end; end.
View Code
相关文章推荐
- 【BZOJ3083/3306】遥远的国度/树 树链剖分+线段树
- BZOJ 3083 遥远的国度 树链剖分 线段树
- bzoj3083 遥远的国度 题解
- 【bzoj3306】 树 dfs序+线段树
- BZOJ3083: 遥远的国度
- BZOJ 3083 遥远的国度 树链剖分
- BZOJ 3306|树|树链剖分
- BZOJ3083: 遥远的国度
- 【Bzoj3083】遥远的国度
- [bzoj3083][树链剖分][lca]遥远的国度
- 【BZOJ 3306】树【LCA、DFS序、线段树】
- 【BZOJ 3083】遥远的国度 树剖
- [bzoj3306]树 dfs序+线段树
- bzoj3083 遥远的国度 树链剖分+树上lca
- BZOJ3083 遥远的国度(树链剖分+线段树)
- BZOJ 3083: 遥远的国度 树链剖分,处理树的换根
- bzoj 3306: 树
- BZOJ_3083_遥远的国度_树链剖分+线段树
- [BZOJ3306]树
- bzoj 3083: 遥远的国度【树链剖分】