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

来源:互联网 发布:mysql 窗口函数 over 编辑:程序博客网 时间:2024/05/16 11:32

这里写图片描述
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.
0 0
原创粉丝点击