SP1487 PT07J - Query on a tree III (主席樹)

SP1487 PT07J - Query on a tree III

題意翻譯

你被給定一棵帶點權的n個點的有根數,點從1到n編號。node

定義查詢 query(x,k): 尋找以x爲根的k大點的編號(從小到大排序第k個點)c++

假設沒有兩個相同的點權。數組

輸入格式: 第一行爲整數n,第二行爲點權,接下來n-1行爲樹邊,接下來一行爲整數m,下面m行爲兩個整數x,k,表明query(x,k)ui

輸出格式: m行,輸出每次查詢的結果。spa

Translated by @vegacx翻譯

題目描述

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

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.code

輸入輸出格式

輸入格式:排序

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.get

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\n",query(rt[id[x]-1],rt[id[x]+size[x]-1],1,n,k));
    }
}
相關文章
相關標籤/搜索