zoukankan      html  css  js  c++  java
  • P2633 Count on a tree(可持久化线段树+树上第K大)

    题意:

    给出一颗点权树,每次询问两点之间第k大的节点。

    题解:

    查询时的check条件换成C[u]+C[v]-C[lca]-C[fa[lca]],其他的和主席树差不多,就是利用前缀和的思想。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    int n,m,q;
    int a[maxn];
    int t[maxn];
    int T[maxn*40];
    int lson[maxn*40];
    int rson[maxn*40];;
    int c[maxn*40];
    int tot;
    void init_hash () {
        for (int i=1;i<=n;i++) t[i]=a[i];
        sort(t+1,t+n+1);
        m=unique(t+1,t+n+1)-t-1;
    }
    int Hash (int x) {
        return lower_bound(t+1,t+m+1,x)-t;
    }
    int build (int l,int r) {
        int root=tot++;
        c[root]=0;
        if (l!=r) {
            int mid=(l+r)>>1;
            lson[root]=build(l,mid);
            rson[root]=build(mid+1,r);
        }
        return root;
    }
    int up (int root,int p,int v) {
        int newRoot=tot++;
        int tmp=newRoot;
        int l=1,r=m;
        while (l<r) {
            int mid=(l+r)>>1;
            if (p<=mid) {
                lson[newRoot]=tot++;
                rson[newRoot]=rson[root];
                newRoot=lson[newRoot];
                root=lson[root];
                r=mid;
            }
            else {
                rson[newRoot]=tot++;
                lson[newRoot]=lson[root];
                newRoot=rson[newRoot];
                root=rson[root];
                l=mid+1;
            }
            c[newRoot]=c[root]+v;
        }
        return tmp;
    }
    int query (int left_root,int right_root,int lca_root,int fa_lca,int k) {
        int l=1,r=m;
        while (l<r) {
            int mid=(l+r)>>1;
            if (c[lson[left_root]]+c[lson[right_root]]-c[lson[lca_root]]-c[lson[fa_lca]]>=k) {
                r=mid;
                left_root=lson[left_root];
                right_root=lson[right_root];
                lca_root=lson[lca_root];
                fa_lca=lson[fa_lca];
            }
            else {
                l=mid+1;
                k-=(c[lson[left_root]]+c[lson[right_root]]-c[lson[lca_root]]-c[lson[fa_lca]]);
                left_root=rson[left_root];
                right_root=rson[right_root];
                lca_root=rson[lca_root];
                fa_lca=rson[fa_lca];
            }
        }
        return l;
    }
    vector<int> g[maxn];
    int father[30][maxn];
    int h[maxn];
    
    void dfs (int u) {
        for (int v:g[u]) {
            if (v==father[0][u])continue;
            T[v]=up(T[u],a[v],1);
            father[0][v]=u;
            h[v]=h[u]+1; 
            dfs(v);
        }
    }
    
    int lca (int x,int y) {
        if (h[x]<h[y]) swap(x,y);
        for (int i=20;i>=0;i--)
            if (h[x]-h[y]>>i) x=father[i][x];
        if (x==y) return x;
        for (int i=20;i>=0;i--) 
            if (father[i][x]!=father[i][y]) {
                x=father[i][x];
                y=father[i][y];
            }
        return father[0][x];
    }
    
    int main () {
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++) scanf("%d",a+i);
        init_hash();
        for (int i=1;i<=n;i++) a[i]=Hash(a[i]);
        for (int i=1;i<n;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x].push_back(y);
            g[y].push_back(x);
        }
        T[0]=build(1,m);
        T[1]=up(T[0],a[1],1);
        dfs(1);
        for (int i=1;i<=20;i++) {
            for (int j=1;j<=n;j++) {
                father[i][j]=father[i-1][father[i-1][j]];
            }
        }
        int ans=0;
        //printf("%d
    ",father[0][1]);
        while (q--) {
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            u^=ans;
            int Lca=lca(u,v);
            //printf("%d %d %d %d
    ",u,v,k,Lca);
            ans=t[query(T[u],T[v],T[Lca],T[father[0][Lca]],k)];
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    典型案例道出“服务台”的价值
    银监会拟允许银行理财产品直接投资
    解读中国版存款保险制度:差别费率+强监管色彩
    央行牵头互联网金融“顶层设计”引业内关注
    央行降息 是农村互联网金融的救命稻草?
    历史上最伟大的 12 位程序员
    年关将至业内警示P2P跑路风险
    央行启动我国征信自律组织研究课题
    windows下开启redis拓展
    php使用curl新增微信临时素材(上传图片)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13601245.html
Copyright © 2011-2022 走看看