您的位置:首页 > 其它

【NOIP2016提高A组集训第5场11.2】行走

2016-11-07 22:16 399 查看


Input

第一行两个整数n和q表示点个数和询问与操作个数

接下来n-1行每行三个整数u,v,c表示u与v之间有一条边权为c的边

接下来q行每行第一个数type

如果type=1那么接下来三个数x,y,v表示一组询问

如果type=2那么接下来两个数p,c表示一组操作

Output

对于每组询问输出一个数表示最后的答案

Sample Input

样例输入1

6 6

1 2 1

1 3 7

1 4 4

2 5 5

2 6 2

1 4 6 17

2 3 2

1 4 6 17

1 5 5 20

2 4 1

1 5 1 3

样例输入2

5 4

1 2 7

1 3 3

3 4 2

3 5 5

1 4 2 100

1 5 4 1

2 2 2

1 1 3 4

Sample Output

样例输出1

2

4

20

3

样例输出2

2

0

2

Data Constraint

对于70%的数据保证 n <= 1000

对于100%的数据保证 n,q <= 105 ,c_i,v_i <= 1018

保证每次修改后的边权小于等于原来的边权且不会小于1

题解

首先我们发现如果答案不为1那么路径上最多只有60个值不为1的边(否则最后的答案小于等于1)。那么我们可以对权值等于1的边并查集,然后对于每一对询问做一次lca,然后往上跑就可以了

贴代码

var
fa,deep:array[0..100005]of longint;
a,f,p:array[0..200005,1..3]of int64;
b:array[0..100005,1..2]of longint;
bz:array[0..100005]of boolean;
ff:array[0..100005,0..18]of longint;
cc:array[0..20]of longint;
i,j,k,l,n,q,x,y,t1,t2,x1,y1:longint;
z:int64;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2,1];
repeat
while a[i,1]<mid do inc(i);
while a[j,1]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure star;
begin
b[a[1,1],1]:=1;
for i:=2 to 2*n-2 do
if a[i,1]<>a[i-1,1] then
begin
b[a[i-1,1],2]:=i-1;
b[a[i,1],1]:=i;
end;
b[a[2*n-2,1],2]:=2*n-2;
end;
procedure make_f(x:longint);
var
i:longint;
begin
bz[x]:=true;
for i:=b[x,1] to b[x,2] do
if (i<>0) and (bz[a[i,2]]=false) then
begin
f[a[i,2],1]:=x;
f[a[i,2],2]:=a[i,3];
deep[a[i,2]]:=deep[x]+1;
make_f(a[i,2]);
end;
end;
function getfather(x:longint):longint;
begin
if fa[x]=x then exit(x)
else fa[x]:=getfather(fa[x]);
exit(fa[x]);
end;
procedure make_ff;
var
i,j:longint;
begin
for j:=1 to 17 do
for i:=2 to n do ff[i,j]:=ff[ff[i,j-1],j-1];
end;
begin
assign(input,'walk.in'); reset(input);
assign(output,'walk.out'); rewrite(output);
readln(n,q);
for i:=1 to n-1 do
begin
readln(a[i,1],a[i,2],a[i,3]);
a[i+n-1,1]:=a[i,2];
a[i+n-1,2]:=a[i,1];
a[i+n-1,3]:=a[i,3];
end;
p:=a;
qsort(1,2*n-2);
star;
deep[1]:=1;
make_f(1);
for i:=1 to n do fa[i]:=i;
for i:=2 to n do
if f[i,2]=1 then
begin
x:=getfather(f[i,1]);
y:=getfather(i);
if x<>y then fa[y]:=x;
end;
for i:=2 to n do ff[i,0]:=f[i,1];
cc[0]:=1;
for i:=1 to 17 do cc[i]:=cc[i-1]*2;
make_ff;
for i:=1 to q do
begin
read(x);
if x=1 then
begin
readln(x,y,z);
x1:=x;
y1:=y;
if deep[x]<deep[y] then
begin
t1:=x;
x:=y;
y:=t1;
end;
t1:=deep[x]-deep[y];
t2:=0;
while t1>0 do
begin
if t1 mod 2=1 then x:=ff[x,t2];
inc(t2);
t1:=t1 div 2;
end;
t1:=deep[x];
for j:=17 downto 0 do
if ff[x,j]<>ff[y,j] then
begin
x:=ff[x,j];
y:=ff[y,j];
t1:=t1-cc[j];
end;
if x<>y then dec(t1);
x:=x1;
while (deep[x]>t1) and (z>0) do
begin
if f[x,2]=1 then
begin
x:=getfather(f[x,1]);
if deep[x]<=t1 then break;
end else
begin
z:=z div f[x,2];
x:=f[x,1];
end;
end;
x:=y1;
while (deep[x]>t1) and (z>0) do
begin
if f[x,2]=1 then
begin
x:=getfather(f[x,1]);
if deep[x]<=t1 then break;
end else
begin
z:=z div f[x,2];
x:=f[x,1];
end;
end;
writeln(z);
end else
begin
readln(x,y);
if f[p[x,2],1]=p[x,1] then
begin
f[p[x,2],2]:=y;
t1:=p[x,2];
t2:=p[x,1];
end
else
begin
f[p[x,1],2]:=y;
t1:=p[x,1];
t2:=p[x,2];
end;
if y=1 then
fa[t1]:=t2;
end;
end;
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: