您的位置:首页 > 其它

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的代码

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: