[JZOJ5131][SDOI省队集训2017]距离

来源:互联网 发布:美工海报设计兼职 编辑:程序博客网 时间:2024/05/17 22:42

题目描述

这里写图片描述

点分治

询问拆成四条到根的询问。
bfs一遍,处理出可持久化点分树。
查询直接查。

#include<cstdio>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=400000+10,maxtot=maxn*30;int son[maxn],sx[maxn],fa[maxn];int rot[maxn],tree[maxtot][4];ll d1[maxn*20],d2[maxn*20];int s1[maxn*20],s2[maxn*20];int h[maxn],go[maxn*2],dis[maxn*2],next[maxn*2],p[maxn],bb[maxn],cc[maxn],zs[maxn];ll d[maxn][20];int belong[maxn][20],f[maxn][20],dep[maxn],zjy[maxn],sta[80];int size[maxn],a[maxn];int h2[maxn*2],g2[maxn*4],di2[maxn*4],n2[maxn*4];int ask[maxn];ll sum[maxn];bool bz[maxn];int i,j,k,l,r,t,nn,n,m,tot,top,cnt,num,czy;ll ans;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}void add(int x,int y,int z){    go[++tot]=y;    dis[tot]=z;    next[tot]=h[x];    h[x]=tot;}void add2(int x,int y,int z){    g2[++num]=y;    di2[num]=z;    n2[num]=h2[x];    h2[x]=num;}void link(int x,int y,int z){    add2(x,y,z);    add2(y,x,z);}void new_build(int x,int y){    int t=h[x];    int i,j,k=0;    while (t){        if (go[t]!=y) bb[++k]=go[t],cc[k]=dis[t];        t=next[t];    }    if (k<=1){        fo(i,1,k) link(x,bb[i],cc[i]);    }    else{        fo(i,1,1) link(x,bb[i],cc[i]);        j=x;        fo(i,2,k){            ++n;            zs[n]=x;            link(j,n,0);            j=n;            link(j,bb[i],cc[i]);        }    }    t=h[x];    while (t){        if (go[t]!=y) new_build(go[t],x);        t=next[t];    }}void dfs(int x,int y){    f[x][0]=y;    dep[x]=dep[y]+1;    int t=h[x];    while (t){        if (go[t]!=y) dfs(go[t],x);        t=next[t];    }}int lca(int x,int y){    if (dep[x]<dep[y]) swap(x,y);    if (dep[x]!=dep[y]){        int j=zjy[dep[x]];        while (j>=0){            if (dep[f[x][j]]>=dep[y]) x=f[x][j];            j--;        }    }    if (x==y) return x;    int j=zjy[dep[x]];    while (j>=0){        if (f[x][j]!=f[y][j]){            x=f[x][j];            y=f[y][j];        }        j--;    }    return f[x][0];}void travel(int x,int y){    a[++top]=x;    int t=h[x];    size[x]=1;    while (t){        if (go[t]!=y&&!bz[go[t]]){            travel(go[t],x);            size[x]+=size[go[t]];        }        t=next[t];    }}void dg(int x,int y,int z,int w){    belong[x][w]=z;    int t=h[x];    while (t){        if (go[t]!=y&&!bz[go[t]]){            d[go[t]][w]=d[x][w]+(ll)dis[t];            dg(go[t],x,z,w);        }        t=next[t];    }}int solve(int x,int y){    top=0;    travel(x,0);    int i,j=x,k=0,t;    while (1){        t=h[j];        while (t){            if (go[t]!=k&&!bz[go[t]]&&size[go[t]]>top/2){                k=j;                j=go[t];                break;            }            t=next[t];        }        if (!t) break;    }    if (!y) rot[0]=j;    t=h[j];    while (t){        if (!bz[go[t]]){            //change(root[j],1,n,go[t],go[t]);            d[go[t]][y]=dis[t];            dg(go[t],j,j,y);        }        t=next[t];    }    bz[j]=1;    belong[j][y]=j;    t=h[j];    while (t){        if (!bz[go[t]]){            son[j]++;            k=solve(go[t],y+1);            sx[k]=son[j];            fa[k]=j;        }        t=next[t];    }    return j;}void bfs(int x,int y){    int i,j,z=p[x],w=rot[y],u,v;    if (x>nn){        rot[x]=rot[y];    }    else{    tot++;    rot[x]=tot;    fo(i,0,20){        //root[tot]=root[w];        fo(j,1,3) tree[tot][j]=tree[w][j];        d1[tot]=d1[w]+d[z][i];        s1[tot]=s1[w]+1;        if (i){            d2[tot]=d2[w]+d[z][i-1];            s2[tot]=s2[w]+1;        }        if (belong[z][i]==z) break;        u=sx[belong[z][i+1]];        v=son[belong[z][i]];        //change(root[tot],1,v,u,tot+1);        tree[tot][u]=tot+1;        tot++;        //w=query(root[w],1,v,u);        w=tree[w][u];    }    }    int t=h[x];    while (t){        if (go[t]!=y) bfs(go[t],x);        t=next[t];    }}void calc(int x,int f){    if (!x) return;    int i,y=rot[x];    fo(i,0,20){        if (i){            ans-=f*d2[y];            ans-=(ll)f*s2[y]*d[k][i-1];        }        ans+=f*d1[y];        ans+=(ll)f*s1[y]*d[k][i];        if (belong[k][i]==k) break;        //y=query(root[y],1,son[belong[k][i]],sx[belong[k][i+1]]);        y=tree[y][sx[belong[k][i+1]]];    }}void write(ll x){    if (!x){        putchar('0');        putchar('\n');        return;    }    top=0;    while (x){        sta[++top]=x%10;        x/=10;    }    while (top) putchar(sta[top--]+'0');    putchar('\n');}int main(){    freopen("dis.in","r",stdin);freopen("dis.out","w",stdout);    czy=read();    n=read();m=read();    nn=n;    fo(i,1,n-1){        j=read();k=read();l=read();        add(j,k,l);add(k,j,l);    }    new_build(1,0);    fo(i,1,n) h[i]=h2[i];    fo(i,1,num){        go[i]=g2[i];        dis[i]=di2[i];        next[i]=n2[i];    }    dfs(1,0);    fo(i,1,n) zjy[i]=floor(log(i)/log(2));    fo(j,1,zjy[n])        fo(i,1,n)            f[i][j]=f[f[i][j-1]][j-1];    fo(i,1,nn) p[i]=read();    tot=top=cnt=0;    solve(1,0);    fo(i,1,n)        if (sx[i]) tree[fa[i]][sx[i]]=i;    tot=n;    fo(i,1,nn) zs[i]=i;    bfs(1,0);    while (m--){        l=read();r=read();k=read();        l^=(czy*ans);r^=(czy*ans);k^=(czy*ans);        ans=0;        calc(l,1);        calc(r,1);        j=zs[lca(l,r)];        calc(j,-1);        j=zs[f[j][0]];        calc(j,-1);        write(ans);    }}