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学习笔记--初识容器类库
一.前言 JAVA中一切皆为对象,因而,持有对象显得尤为重要. 在JAVA中,我们可以通过创建一个对象的引用的方式来持有对象: HoldingObject holding; 也可以创建一个对象数组来持 ...
- 福利,一张图看懂IT售前工程师修炼之道
职场中的新人如何自我定位? 如何深刻理解IT售前这个职位? 如何从IT售前菜鸟成长为IT售前专家? 推荐这本书<IT售前工程师修炼之道> 本书精华内容 售前的重要性 售前要有逻辑能力 售前 ...
- DruidDataSource源码分析
最近公司要求基于阿里的DruidDataSource来做一个连接池监控 , 正好之前没有看过DruidDataSource的源码 , 便自己看了四个多小时写了一些自己的理解 , 给大家分享一下 , 如 ...
- wepy中如何使用stylus等样式预处理器
wepy中如何使用stylus等样式预处理器 一.如何在wepy中使用stylus 1.安装wepy-compiler-stylus(以及stylus, stylus-loader) npm inst ...
- Oracle数据库拼音首字母模糊搜索
1.建立函数 CREATE OR REPLACE FUNCTION F_PINYIN(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS V_COMPARE ); V_RET ...
- Scrum立会报告+燃尽图 01
此作业要求:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2190] 一.小组介绍 组长:王一可 组员:范靖旋,王硕,赵佳璐,范洪达,祁 ...
- 第九周个人PSP
11.10--11.16本周例行报告 1.PSP(personal software process )个人软件过程. C(类别) C(内容) ST(开始时间) ET(结束时间) INT(间隔时间) ...
- Python if后直接跟数字或字符串
(1)如果if后面的条件是数字,只要这个数字不是0,python都会把它当做True处理,见下面的例子 if 15: print 'YES' 输出YES,但是如果数字是0,就会被认为是False. ( ...
- 一些有趣的erlang项目
这里会收集一些erlang项目,有需可以转. erlang-bookmarks Scaling Erlang High Performance Erlang - Finding Bottlenecks ...
- QMetaEnum利用Qt元数据实现枚举(enum)类型值及字符串转换
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QMetaEnum利用Qt元数据实现枚举(enum)类型值及字符串转换 本文地址:ht ...