• SP1487 PT07J


    SP1487 PT07J - Query on a tree III

    题意翻译

    你被给定一棵带点权的n个点的有根数,点从1到n编号。

    定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点)

    假设没有两个相同的点权。

    输入格式: 第一行为整数n,第二行为点权,接下来n-1行为树边,接下来一行为整数m,下面m行为两个整数x,k,代表query(x,k)

    输出格式: m行,输出每次查询的结果。

    Translated by @vegacx

    题目描述

    You are given a node-labeled rooted tree with n nodes.

    Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels.

    输入输出格式

    输入格式:

    The first line contains one integer n (1 <= n <= 10 ^{5}5 ). The next line contains n integers _l {i}i​ (0 <= _l {i}i​ <= 10 ^{9}9 ) which denotes the label of the i-th node.

    Each line of the following n - 1 lines contains two integers u, v. They denote there is an edge between node _u_and node v. Node 1 is the root of the tree.

    The next line contains one integer m (1 <= m <= 10 ^{4}4 ) which denotes the number of the queries. Each line of the next m contains two integers x, k. (k <= the total node number in the subtree of x)

    输出格式:

    For each query (x, k), output the index of the node whose label is the k-th largest in the subtree of the node x.

    输入输出样例

    输入样例#1:

    5
    1 3 5 2 7
    1 2
    2 3
    1 4
    3 5
    4
    2 3
    4 1
    3 2
    3 2

    输出样例#1:

    5
    4
    5
    5

    Solution

    传送门
    树上静态主席树...

    显然我们要根据dfs序来建立主席树,也正因如此,所以我们在dfs的过程中要重新赋一下值,给当前dfs序为i的节点另开两个存值的数组,一个是原数组,一个离散数组,这样值才能与主席树对上号

    
    void dfs(int u,int fa) {
        id[u]=++cnt, a[cnt]=b[cnt]=w[u], inv[cnt]=u, size[u]=1;//inv[]存的是通过dfs序找到节点
        for (int i=head[u];i;i=nex[i]) {
            if (to[i]==fa) continue;
            dfs(to[i],u); size[u]+=size[to[i]];
        }
    }
    

    在加入节点的过程中,因为题目问的是节点编号而不是值,我们还要把当前值赋为节点编号

    至于查询,就是以dfs序和子树大小来查,因为是连续的...
    其实如果会静态主席树,这道题稍微难一点的主要还是建树,会建树就会查询了

    Code

    #include<bits/stdc++.h>
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define rg register
    #define mid ((l+r)>>1)
    #define in(i) (i=read())
    using namespace std;
    
    const int N=1e5+10;
    
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
        return ans*=f;
    }
    
    int T,n,m,tot,cur,cnt;
    int w[N],a[N],b[N],id[N],inv[N],size[N],ans[N];
    int to[N<<1],nex[N<<1],head[N];
    int rt[N<<5],lc[N<<5],rc[N<<5],sum[N<<5];
    
    void add(int a,int b) {
        to[++cur]=b,nex[cur]=head[a],head[a]=cur;
        to[++cur]=a,nex[cur]=head[b],head[b]=cur;
    }
    
    void build(int &u,int l,int r) {
        u=++tot,sum[u]=0;
        if (l==r) return;
        build(lc[u],l,mid);
        build(rc[u],mid+1,r);
    }
    
    void update(int &u,int l,int r,int pre,int x) {
        u=++tot;
        sum[u]=sum[pre]+1,lc[u]=lc[pre],rc[u]=rc[pre];
        if (l==r) return;
        if(x<=mid) update(lc[u],l,mid,lc[pre],x);
        else update(rc[u],mid+1,r,rc[pre],x);
    }
    
    int query(int u,int v,int l,int r,int k) {
        if(l==r) return ans[l];
        int rest=sum[lc[v]]-sum[lc[u]];
        if(k<=rest) return query(lc[u],lc[v],l,mid,k);
        else return query(rc[u],rc[v],mid+1,r,k-rest);
    }
    
    void dfs(int u,int fa) {
        id[u]=++cnt, a[cnt]=b[cnt]=w[u], inv[cnt]=u, size[u]=1;
        for (int i=head[u];i;i=nex[i]) {
            if (to[i]==fa) continue;
            dfs(to[i],u); size[u]+=size[to[i]];
        }
    }
    
    int main()
    {
        in(n);
        for (int i=1;i<=n;i++) in(w[i]);
        for (int i=1,x,y;i<n;i++) in(x), in(y), add(x,y);
        dfs(1,0);
        sort(b+1,b+1+n); build(rt[0],1,n);
        for (int i=1;i<=n;i++) {
            a[i]=lower_bound(b+1,b+1+n,a[i])-b;
            ans[a[i]]=inv[i];
            update(rt[i],1,n,rt[i-1],a[i]);
        }
        in(m);
        for (int i=1,x,k;i<=m;i++) {
            in(x), in(k);
            printf("%d
    ",query(rt[id[x]-1],rt[id[x]+size[x]-1],1,n,k));
        }
    }
    
    
  • 相关阅读:
    python随笔:邮箱题目
    05 小程序自定义组件
    04 小程序常用组件-view text rich-text icon swiger
    03 小程序语法-WXSS样式-尺寸-样式 -选择器
    02 小程序语法-数据绑定与事件绑定
    01 小程序入门与vscode开发加装插件
    JAVA25-Git、Vue.js
    JAVA14-File类、递归、字节流、字符流、缓冲流、转换流、序列化流、Files
    JAVA13-异常、线程、同步、等待与唤醒案例、线程池、Lambda表达式
    JAVA12-Scanner类、Random类、ArrayList类、String类、static、Arrays类、Math类、静态方法
  • 原文地址:https://www.cnblogs.com/real-l/p/9873035.html
Copyright © 2020-2023  润新知