SP1487 PT07J - Query on a tree III (主席树)
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\n",query(rt[id[x]-1],rt[id[x]+size[x]-1],1,n,k));
}
}
SP1487 PT07J - Query on a tree III (主席树)的更多相关文章
- SP1487 PT07J - Query on a tree III 主席树+dfs序
Code: #include<iostream> #include<cstdio> #include<algorithm> #include<string&g ...
- 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 ...
- 【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 ...
- BZOJ1803Spoj1487 Query on a tree III——主席树
题目大意 给一棵有点权的n个点的有根树,保证任意两点的点权不同,m次询问每次询问x的子树中权值第k大的点. 输入 先输入n,然后每个点点权,再输入n-1行每行两个数x,y代表x和y相连,再输入m,之后 ...
- bzoj 1803: Spoj1487 Query on a tree III(主席树)
题意 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数n, ...
- 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 ...
- [SPOJ-PT07J] Query on tree III (主席树)
题意翻译 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数 ...
- [ SPOJ PT07J ] Query on a tree III
\(\\\) Description 其实这题才是正版的 Qtree3...... 给定 \(n\) 个点,以 \(1\) 号节点为根的树,点有点权. \(m\) 次询问 以 \(x\) 为根的子树内 ...
- 「SPOJ1487」Query on a tree III
「SPOJ1487」Query on a tree III 传送门 把树的 \(\text{dfs}\) 序抠出来,子树的节点的编号位于一段连续区间,然后直接上建主席树区间第 \(k\) 大即可. 参 ...
随机推荐
- Java解惑之TreeSet是如何去重的
引言: 最近在处理一个问题,大致是这个样子,从数据库里面取出一个集合,取出来的数据放到一个JavaBean里面.结果得到的集合长度为1. TreeSetSet的一个实现,默认实现排序:故TreeSet ...
- python基础知识-03-字符串
python其他知识目录 1.for循环遍历字符串中单个字符 s_str="mcw" for i in s_str: print(i) -----------结果: m c w 2 ...
- linux 性能分析命令及其解释
很多时候,我们需要对linux上运行的环境大体有一个了解,那么久需要大体知道当前系统的相关资源的使用情况,那么可以用一些linux提供的丰富的命令来查看 性能分析 vmstat 虚拟内存统计 用法 U ...
- Beta发布—美工+文案
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2408 视频展示地址:https://www.bilibili.com/v ...
- 20172321 2018-2019《Java软件结构与数据结构》第三周学习总结
教材学习内容总结 第五章 5.1概述 队列是一种线性集合,其元素从一端加入,从另一端删除:队列的处理方式是先进先出(First in First out). 与栈的比较(LIFO) 栈是一端操作,先进 ...
- TDGA-需求分析
李青:绝对的技术控,团队中扮演“猪”的角色,勤干肯干,是整个团队的主心骨,课上紧跟老师的步伐,下课谨遵老师的指令,课堂效率高,他的编程格言“没有编不出来的程序,只有解决不了的bug”. 胡金辉:半两油 ...
- maven 实践 :管理依赖
有人认为Maven是一个依赖管理工具,当然这种想法是错误的(确切的说Maven是一个项目管理工具,贯穿了整个项目生命周期,编译,测试,打包,发布...),但Maven给人造成这种错误的印象也是有原因的 ...
- (十二)Jmeter之Bean Shell的使用(一)
一.什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanS ...
- 修改mac的hosts文件
第一步:请先打开 Mac 系统中的 Finder 应用,接下来请按快捷键组合 Shift+Command+G 三个组合按键,并输入 Hosts 文件的所在路径:/etc/hosts , 随后即可在 F ...
- IDEA换行CRLF, LF, CR的解释和默认设置
在window下开发有一个大坑,就是换行默认是CRLF,也就是回车换行,但是Linux下只有换行LF,这样代码提交后,会出现编译问题,所以最好的办法是在IDEA下设置默认为LF. 首先我们先介绍CRL ...