zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    mina之小小总结(标准的菜鸟级别,行家勿入)
    tomcat(就一句话,自己的日记性质)
    MINA转自itoyo
    java web(没含量的,百科上的)
    解决VS.NET 2008中aspx文件没有设计界面
    正则表达式教程
    [VB] Option Explicit
    sql自定義函數 包含遊標
    sql 中 null+others=?
    实用手机号、IP、身份证号、歌曲查询接口
  • 原文地址:https://www.cnblogs.com/carcar/p/11503205.html
Copyright © 2011-2022 走看看