题意翻译

你被给定一棵带点权的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序,然后记录每个节点 siz,再用主席树维护即可。

然后查询的时候查询 ( b[i] , b[i]+siz[i]-1 ) ,需要注意的是输出的是编号。


代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
struct sj{int to,next;}line[maxn*2];
int size,n,m,num,q,siz[maxn];
int head[maxn],id[maxn],tot,idx[maxn];
int a[maxn],b[maxn],c[maxn],T[maxn];
int L[maxn*20],R[maxn*20],sum[maxn*20];
void add(int x,int y)
{
line[++size].to=y;
line[size].next=head[x];
head[x]=size;
}
int old[maxn];
void dfs(int x)
{
siz[x]=1;
a[++num]=c[x];
id[x]=num; b[num]=a[num];
old[num]=x;
for(int i=head[x];i;i=line[i].next)
{
int tt=line[i].to;
if(!siz[tt])
{
dfs(tt);
siz[x]+=siz[tt];
}
}
} int build(int l,int r)
{
int rt=++tot;
if(l!=r)
{
int mid=(l+r)/2;
L[rt]=build(l,mid);
R[rt]=build(mid+1,r);
}
return rt;
} int update(int pre,int l,int r,int x)
{
int rt=++tot;
L[rt]=L[pre];
R[rt]=R[pre];
sum[rt]=sum[pre]+1;
int mid=(l+r)/2;
if(l!=r)
{
if (x<=mid) L[rt]=update(L[pre],l,mid,x);
else R[rt]=update(R[pre],mid+1,r,x);
}
return rt;
} int query(int x,int y,int l,int r,int k)
{
if(l==r)return l;
int now=sum[L[y]]-sum[L[x]];
int mid=(l+r)/2;
if(now>=k) return query(L[x],L[y],l,mid,k);
else return query(R[x],R[y],mid+1,r,k-now);
} int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<n;i++)
{
int x,y; scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(1);
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
T[0]=build(1,m);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+m,a[i])-b,
T[i]=update(T[i-1],1,m,a[i]);
idx[a[i]]=old[i];
}
scanf("%d",&q);
while(q--)
{
int x,k;
scanf("%d%d",&x,&k);
int p=query(T[id[x]-1],T[id[x]+siz[x]-1],1,m,k);
printf("%d\n",idx[p]);
}
}
/*
5
1 3 5 2 7
1 2
2 3
1 4
3 5
4
2 3
4 1
3 2
3 2
*/

[SPOJ-PT07J] Query on tree III (主席树)的更多相关文章

  1. SP1487 PT07J - Query on a tree III (主席树)

    SP1487 PT07J - Query on a tree III 题意翻译 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小 ...

  2. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  3. BZOJ1803Spoj1487 Query on a tree III——主席树

    题目大意 给一棵有点权的n个点的有根树,保证任意两点的点权不同,m次询问每次询问x的子树中权值第k大的点. 输入 先输入n,然后每个点点权,再输入n-1行每行两个数x,y代表x和y相连,再输入m,之后 ...

  4. bzoj 1803: Spoj1487 Query on a tree III(主席树)

    题意 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数n, ...

  5. SP1487 PT07J - Query on a tree III 主席树+dfs序

    Code: #include<iostream> #include<cstdio> #include<algorithm> #include<string&g ...

  6. BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

    BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with ...

  7. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  8. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  9. SPOJ PT07J - Query on a tree III(划分树)

    PT07J - Query on a tree III #tree You are given a node-labeled rooted tree with n nodes. Define the ...

随机推荐

  1. 使用FontDialog组件设置字体

    实现效果: 知识运用: FontDialog组件的Font属性 //获取或设置选定的字体 public Font Font  { get;set; } 实现代码: private void butto ...

  2. bower使用

    1,先安装nodejs(npm),Git 2,安装bower cmd执行到在项目文件夹下路径,执行npm install bower 3,执行bower init  项目根目录下将生成bower.js ...

  3. Chunky Monkey-freecodecamp算法题目

    Chunky Monkey(猴子吃香蕉, 分割数组) 要求 把一个数组arr按照指定的数组大小size分割成若干个数组块. 思路 利用size值和while语句确定切割数组的次数(定义temp将siz ...

  4. BZOJ-3679(数位DP)

    #include <bits/stdc++.h> using namespace std; typedef long long ll; ll a,b; int k[20]; ll dp[2 ...

  5. charles抓手机包

    charles抓手机包   如果是使用charles抓包.一定要tm的保证手机和电脑连的是一个网.   1.proxy setting,查看charles,端口 2.勾选   3.ipconfig,查 ...

  6. webpack4搭建Vue开发环境笔记~~持续更新

    项目git地址 一.node知识 __dirname: 获取当前文件所在路径,等同于path.dirname(__filename) console.log(__dirname); // Prints ...

  7. STA basic

  8. 面向对象之元类(metaclass)

    一.前言: 要搞懂元类必须要搞清楚下面几件事: 类创建的时候,内部过程是什么样的,也就是我们定义类class 类名()的过程底层都干了些啥 类的调用即类的实例化过程的了解与分析 我们已经知道元类存在的 ...

  9. 转载:使用Pandas进行数据匹配

    使用Pandas进行数据匹配 本文转载自:蓝鲸的网站分析笔记 原文链接:使用Pandas进行数据匹配 目录 merge()介绍 inner模式匹配 lefg模式匹配 right模式匹配 outer模式 ...

  10. 20个必不可少的Python库也是基本的第三方库

    个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们是: Requests.Kenneth Reitz写的最富盛名的http库.每个Python程序员都应该有它. Scrapy. ...