SP913 QTREE2 - Query on a tree II

SP913 QTREE2 - Query on a tree II

LCA真香

(dep为初始化,3秒挂)

第一问:经典树上差分

第二问:分两类

1.第k个点为u的父亲 直接跳

2.转换一下再跳

代码:

#include
using namespace std;
const int N=10005;
int T;
int n;
int hed[N<<1],tal[N<<1],val[N<<1],nxt[N<<1],cnt=0;
int f[N][30];
int dep[N];
int w[N][30];
char s[30];
int A,B,C;
void addege(int x,int y,int z){
    cnt++;
    tal[cnt]=y;
    val[cnt]=z; 
    nxt[cnt]=hed[x];
    hed[x]=cnt;
} 
void dfs(int u,int fa){
    f[u][0]=fa;
    for(int i=hed[u];i;i=nxt[i]){
        int v=tal[i];
        if(v==fa) continue;
        dep[v]=dep[u]+1; 
        w[v][0]=val[i];
        dfs(v,u);
    }
}
int jump(int x,int k){
    for(int i=20;i>=0;i--){
        if(k>=(1<1){
            x=f[x][i];
            k-=(1<<i);
        }
    } 
    return x; 
}
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
int lca1(int x,int y){
    int sum=0;
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--) if(dep[f[x][i]]>=dep[y]) sum+=w[x][i],x=f[x][i];
    if(x==y) return sum;
    for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) sum+=w[x][i],sum+=w[y][i],x=f[x][i],y=f[y][i];
    sum+=w[x][0],sum+=w[y][0]; 
    return sum;
}
int lca2(int x,int y,int k){
    int LCA=lca(x,y);
    if(dep[x]-dep[LCA]+1<=k){
        k=dep[x]+dep[y]-(dep[LCA]*2)+2-k;
        x=y;
    }
    return jump(x,k);
}
int main(){
    cin>>T;
    while(T--){
        cnt=0;
        memset(w,0,sizeof(w));
        memset(dep,0,sizeof(dep));
        memset(f,0,sizeof(f));
        memset(hed,0,sizeof(hed));
        scanf("%d",&n);
        for(int i=1;i){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            addege(x,y,z);
            addege(y,x,z);
        }
        dep[1]=1;
        dfs(1,1);
        for(int j=1;j<=20;j++){
            for(int i=1;i<=n;i++){
                f[i][j]=f[f[i][j-1]][j-1];
                w[i][j]=w[i][j-1]+w[f[i][j-1]][j-1];
            }
        }
        while(1){
            scanf("%s",s);
            if(s[1]=='O'){
                break;
            }
            else if(s[1]=='I'){
                scanf("%d%d",&A,&B);
                printf("%d\n",lca1(A,B));
            }
            else if(s[1]=='T'){
                scanf("%d%d%d",&A,&B,&C);
                printf("%d\n",lca2(A,B,C));
            }
        }
    }
    

    return 0;
}

 

你可能感兴趣的:(SP913 QTREE2 - Query on a tree II)