AtCoder Beginner Contest 133 F - Colorful Tree

The meaning of problems: given a tree of n points, each side has two long sides and color properties, the n query, asking each side of the long side becomes a color x y u to v Q path length What it is, independent of inquiry.

Solution: This question is very interesting. Solution Reference https://www.cnblogs.com/Tieechal/p/11185912.html the big brother here that my understanding.

For each inquiry (x, y, u, v) Compare the answer is obviously dist (u, v) + (sumlen [x] -sumcnt [x] * y), but we do not consider this question online do offline . But the formula is designed to answer two points, how to do it off-line? Here the use of a more clever way: the use of LCA asked to split into three points, then you can direct it again dfs offline. Specifically, is to ask each split into u, v, lca three points, three points of inquiry contributed to the cause is the answer, each point p contribution is: root path to point p + p points to the root path path sum x of the color - the color of the point p to the root number of sides x * y (coefficient of three points of course is not the same). LCA demand based on experience from two points of fact, the principle is easy to see here is almost as well as to each count with two repeat part is then removed to lca is correct.

Then the first dfs again seek LCA, and then off again dfs handles inquiries on it.

 

See details Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,t;
typedef long long LL;
struct query{
    int x,y,u,v;
    long long ans;
}Q[N];
vector<int> v[N],b[N];

int cnt,head[N],nxt[N<<1],to[N<<1],col[N<<1],len[N<<1];
void add_edge(int x,int y,int c,int d) {
    nxt[++cnt]=head[x]; to[cnt]=y; col[cnt]=c; len[cnt]=d; head[x]=cnt;
}

int dep[N],f[N][20];
void dfs1(int x,int fa,int d) {
    dep[x]=d;
    for (int i=head[x];i;i=nxt[i]) {
        int y=to[i];
        if (y==fa) continue;
        f[y][0]=x;
        for (int j=1;j<=t;j++) f[y][j]=f[f[y][j-1]][j-1];
        dfs1(y,x,d+1);
    }
}

int LCA(int x,int y) {
    if (dep[x]>dep[y]) swap(x,y);
    for (int i=t;i>=0;i--)
        if (dep[f[y][i]]>=dep[x]) y=f[y][i];
    if (x==y) return x;
    for (int i=t;i>=0;i--)
        if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];        
}

int sumc[N],sumd[N];
void dfs2(int x,int fa,int dis) {
    for (int i=0;i<v[x].size();i++) {
        int id=v[x][i];
        Q[id].ans+=(LL)dis*b[x][i];
        Q[id].ans-=(LL)sumd[Q[id].x]*b[x][i];
        Q[id].ans+=(LL)sumc[Q[id].x]*Q[id].y*b[x][i];
    }
    for (int i=head[x];i;i=nxt[i]) {
        int y=to[i];
        if (y==fa) continue;
        sumc[col[i]]++;
        sumd[col[i]]+=len[i];
        dfs2(y,x,dis+len[i]);
        sumc[col[i]]--;
        sumd[col[i]]-=len[i];
    }
}

int main()
{
    cin>>n>>m;
    t=log2(n)+1;
    for (int i=1;i<n;i++) {
        int x,y,c,d;
        scanf("%d%d%d%d",&x,&y,&c,&d);
        add_edge(x,y,c,d);
        add_edge(y,x,c,d);
    }
    dfs1(1,0,1);
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d%d",&Q[i].x,&Q[i].y,&Q[i].u,&Q[i].v);
        v[Q[i].u].push_back(i); b[Q[i].u].push_back(1);
        v[Q[i].v].push_back(i); b[Q[i].v].push_back(1);
        int lca=LCA(Q[i].u,Q[i].v);
        v[lca].push_back(i); b[lca].push_back(-2);
    }
    dfs2(1,0,0);
    for (int i=1;i<=m;i++) printf("%lld\n",Q[i].ans);
    return 0;    
} 

 

Guess you like

Origin www.cnblogs.com/clno1/p/11402711.html