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\) 大即可. 参 ...
随机推荐
- 【springmvc+mybatis项目实战】杰信商贸-7.生产厂家新增
我们要实现新的功能,就是生产厂家的新增先来回顾一下系统架构图我们数据库这边已经建好表了,接下来要做的就是mapper映射 编辑FactoryMapper.xml文件,加入“添加”的逻辑配置代码块 &l ...
- 排序(C语言实现)
读数据结构与算法分析 插入排序 核心:利用的是从位置0到位置P都是已排序的 所以从位置1开始排序,如果当前位置不对,则和前面元素反复交换重新排序 实现 void InsertionSort(Eleme ...
- Openstack 10 云环境安装
概述 资源规划 Undercloud Installation Overcloud Installation Trouble Shooting 附录 本指南介绍了如何使用 Red Hat OpenSt ...
- 音频分析框架pyAudioAnalysis文档
“ pyAudioAnalysis是一个非常好用且强大的音频分析开源工具,能实现音频的特征提取.分类和回归模型的训练和执行,以及其他一些实用的功能.此外,本文档并非直译,也有部分比较简略,可以结合源码 ...
- 福利,一张图看懂IT售前工程师修炼之道
职场中的新人如何自我定位? 如何深刻理解IT售前这个职位? 如何从IT售前菜鸟成长为IT售前专家? 推荐这本书<IT售前工程师修炼之道> 本书精华内容 售前的重要性 售前要有逻辑能力 售前 ...
- springboot集成jpa,在postgresql数据库中创建主键自增表
依赖文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/ ...
- 在Emacs 23里字体的调整(转自ChinaUnix.net)
首先,在Emacs中,通过菜单Options --> Set Default Font,设置好你喜欢的字体. 然后,把光标放到你所在的字体上,用命令M-x describe-font来查看你当前 ...
- Scrum Meeting Beta - 4
Scrum Meeting Beta - 4 NewTeam 2017/12/2 地点:新主楼F座二楼 任务反馈 团队成员 完成任务 计划任务 安万贺 完成了部分页面标题栏颜色的修改和字体的调整Iss ...
- 【final】140字互评②
按照产品发布顺序 nice!----约吧 我们的团队展示相对于上次的手足无措,有了一定进步.但是整体还是不那么流畅总结起来的缺点是: 1.发布时,摄像头不清晰 且抖动 我们没有把摄像头固定,并且为了让 ...
- 新手必备!11个强大的 Visual Studio 调试技巧
简介 调试是软件开发周期中很重要的一部分.它具有挑战性,同时也很让人疑惑和烦恼.总的来说,对于稍大一点的程序,调试是不可避免的.最近几年,调试工具的发展让很多调试任务变的越来越简单和省时. 这篇文章总 ...