codeforces gym #101161E

题目链接:

http://codeforces.com/gym/101161/attachments

题意:

给出节点数为$n$的树

有$q$次询问,输出$a$节点到$b$节点路程中,经过的边的中位数

数据范围:

$1leq n leq 100000$

$1leq q leq 100000$

分析: 

建一颗主席树,不同的是,节点的根继承的是父节点的根

再用$lca$求出公共祖先$tree[a]+tree[b]-2*tree[lca(a,b)]$

ac代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 5e4+100;
struct Node{
    int L,R,num;
}tree[maxn*20];
int dep[maxn],fa[maxn][20],n,cnt;
int root[maxn],vis[maxn];
vector<pii>ve[maxn];

void update(int x,int&root,int st,int en){
    tree[++cnt]=tree[root];
    root=cnt;
    tree[root].num++;
    if(st==en)return ;
    int md=(st+en)/2;
    if(x<=md)
        update(x,tree[root].L,st,md);
    else
        update(x,tree[root].R,md+1,en);
}

void dfs(int x,int fx,int w){
    if(vis[x])return ;
    vis[x]=1;
    root[x]=root[fx];
    if(x!=1)update(w,root[x],1,1e5);
    dep[x]=dep[fx]+1;
    fa[x][0]=fx;
    for(int i=1;(1<<i)<dep[x];i++)
        fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=0;i<ve[x].size();i++)
        dfs(ve[x][i].first,x,ve[x][i].second);
}
int lca(int a,int b){
    if(dep[a]>dep[b])swap(a,b);
    for(int i=19;i>=0;i--)
        if(dep[fa[b][i]]>=dep[a])b=fa[b][i];
    if(a==b)return a;
    for(int i=19;i>=0;i--)
        if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
    return fa[a][0];
}

int quer(int a,int b,int c,int st,int en,int k){
    if(st==en)return st;
    int dd=tree[tree[a].L].num+tree[tree[b].L].num-2*tree[tree[c].L].num;
    //cout<<dd<<" "<<k<<endl;
    int md=(st+en)/2;
    if(dd>=k)return quer(tree[a].L,tree[b].L,tree[c].L,st,md,k);
    return quer(tree[a].R,tree[b].R,tree[c].R,md+1,en,k-dd);
}
int main()
{
    int T,q;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        cnt=0;
        for(int i=1;i<=n;i++){
            ve[i].clear();
            vis[i]=0;
            for(int j=0;j<20;j++)
                fa[i][j]=0;
        }
        for(int i=1;i<=n-1;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            ve[a].push_back(make_pair(b,c));
            ve[b].push_back(make_pair(a,c));
        }

        dfs(1,0,-1);
        //cout<<fa[6][2]<<endl;
        scanf("%d",&q);
        while(q--){
            int a,b,c;
            scanf("%d %d",&a,&b);
            c=lca(a,b);
            int len=dep[a]+dep[b]-2*dep[c];
            //cout<<c<<" "<<len<<endl;
            if(len%2==0){
                int ans1=quer(root[a],root[b],root[c],1,1e5,len/2);
                int ans2=quer(root[a],root[b],root[c],1,1e5,len/2+1);
                printf("%d",(ans1+ans2)/2);
                if((ans1+ans2)%2)printf(".5");
                else printf(".0");
            }
            else
                printf("%d.0",quer(root[a],root[b],root[c],1,1e5,len/2+1));
            printf("
");
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/carcar/p/11503205.html