SPOJ PT07J - Query on a tree III(划分树)
PT07J - Query on a tree III
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.
Input
The first line contains one integer n (1 <= n <= 105). The next line contains n integers li (0 <= li <= 109) 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 <= 104) 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)
Output
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.
Example
Input:
5
1 3 5 2 7
1 2
2 3
1 4
3 5
4
2 3
4 1
3 2
3 2 Output:
5
4
5
5
【分析】给你一棵树以及每个节点的权值,求某个节点以及往下子孙中第K大的节点是哪个。
先DFS给每个节点编号,然后对于每个节点记录他的开始编号和结束编号,然后就是划分树模板了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)+1)
using namespace std;
typedef long long ll;
const int N=1e5+;
const int M=1e6+;
int le[N],re[N],lab[N],sorted[N];
int n,m,k,num=;
map<int,int>mp;
struct Edge {
int to,next;
} edg[N*];
int head[N],tot;
void init() {
tot = ;
memset(head,-,sizeof(head));
}
void addedge(int u,int v) {
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u,int fa) {
le[u]=++num;
sorted[num]=lab[u];
for(int i=head[u]; i!=-; i=edg[i].next) {
int v=edg[i].to;
if(v!=fa) {
dfs(v,u);
}
}
re[u]=num;
}
int tree[][N];
int toleft[][N];
void build(int l,int r,int dep) {
if(l==r)return;
int mid=(l+r)>>;
int same=mid-l+;
for(int i=l; i<=r; i++)
if(tree[dep][i]<sorted[mid])
same--;
int lpos=l;
int rpos=mid+;
for(int i=l; i<=r; i++) {
if(tree[dep][i]<sorted[mid]) { //去左边
tree[dep+][lpos++]=tree[dep][i];
} else if(tree[dep][i]==sorted[mid]&&same>) { //去左边
tree[dep+][lpos++]=tree[dep][i];
same--;
} else //去右边
tree[dep+][rpos++]=tree[dep][i];
toleft[dep][i]=toleft[dep][l-]+lpos-l;//从1到i放左边的个数
}
build(l,mid,dep+);//递归建树
build(mid+,r,dep+);
}
void initBuild() {
for(int i=; i<; i++)tree[i][]=toleft[i][]=;
for(int i=; i<=n; i++) {
tree[][i]=sorted[i];
}
sort(sorted+,sorted+n+);
build(,n,);
} int query(int L,int R,int l,int r,int dep,int k) {
if(l==r)return tree[dep][l];
int mid=(L+R)>>;
int cnt=toleft[dep][r]-toleft[dep][l-];
if(cnt>=k) {
//L+查询区间前去左边的数的个数
int newl=L+toleft[dep][l-]-toleft[dep][L-];
//左端点+查询区间会分入左边的数的个数
int newr=newl+cnt-;
return query(L,mid,newl,newr,dep+,k);//注意
} else {
//r+区间后分入左边的数的个数
int newr=r+toleft[dep][R]-toleft[dep][r];
//右端点减去区间分入右边的数的个数
int newl=newr-(r-l-cnt);
return query(mid+,R,newl,newr,dep+,k-cnt);//注意
}
}
int main() {
int u,v,x;
init();
scanf("%d",&n);
for(int i=; i<=n; i++){
scanf("%d",&lab[i]);
mp[lab[i]]=i;
}
for(int i=; i<n; i++) {
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(,);
initBuild();
scanf("%d",&m);
while(m--){
scanf("%d%d",&x,&k);
u=le[x];v=re[x];
int ans=query(,n,u,v,,k);
printf("%d\n",mp[ans]);
}
return ;
}
SPOJ PT07J - Query on a tree III(划分树)的更多相关文章
- SP1487 PT07J - Query on a tree III (主席树)
SP1487 PT07J - Query on a tree III 题意翻译 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小 ...
- [ SPOJ PT07J ] Query on a tree III
\(\\\) Description 其实这题才是正版的 Qtree3...... 给定 \(n\) 个点,以 \(1\) 号节点为根的树,点有点权. \(m\) 次询问 以 \(x\) 为根的子树内 ...
- SP1487 PT07J - Query on a tree III 主席树+dfs序
Code: #include<iostream> #include<cstdio> #include<algorithm> #include<string&g ...
- 【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 ...
- SPOJ 1487 Query on a tree III(划分树)
题目链接:http://www.spoj.com/problems/PT07J/ 题意:给出一个有根树,1为根节点,每个节点有权值.若干询问,询问以u为根的子树中权值第K小的节点编号. 思路:DFS一 ...
- SPOJ 375. Query on a tree (动态树)
375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...
- Problem: Query on the tree(二分+划分树)
题目链接: Problem: Query on the tree Time limit: 1s Mem limit: 64 MB Problem Description There ...
- 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, ...
随机推荐
- [NOIP2017 TG D2T3]列队
题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$. 现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最 ...
- 雪碧图background-position的rem用法
background的雪碧图配合rem就正常写即可,要加上background-size,大小为sprites的原图尺寸,宽高为一帧的尺寸.例如: .player{ width: 2.32rem; / ...
- 使用adobe pdf去除PDF文档中的批量雷同文本
一.问题的提出 MgoSoft tiff to pdf软件没有提供中国地区的非VISA用户的购买渠道,中国通常都是银联标识走天下,卡不是VISA买不了这样的软件, 那么, MgoSoft tiff t ...
- POJ1847:Tram(最短路)
Tram Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 20116 Accepted: 7491 题目链接:http:/ ...
- bzoj 1201[HNOI2005]数三角形 1202 [HNOI2005]狡猾的商人 暴力 权值并查集
[HNOI2005]数三角形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 349 Solved: 234[Submit][Status][Disc ...
- bzoj 5099 [POI2018]Pionek 计算几何 极角排序
[POI2018]Pionek Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 269 Solved: 80[Submit][Status][Disc ...
- 获取oracle当前系统设置了哪些事件
ALTER SESSION SET EVENTS '10046 trace name context forever,level 12' 会话已更改. DECLARE EVENT_LEVEL NUMB ...
- 前端面试:css预处理
css预处理定义: 定义了一种新的语言,其基本思想是用一种专门编程语言,为css增加了一些编程的特性,将css作为目标生成文件,然后开发者就只要使用这种语言进行编码工作. 几种预处理语言 sass l ...
- js密码的匹配正则
匹配的密码是 数字大写或者小写的字母.符号. if(pwd.match(/[\d]/) && pwd.match(/[A-Za-z]/) && pwd.match(/[ ...
- 汕头市队赛 SRM16 T2
描述 猫和老鼠,看过吧?猫来了,老鼠要躲进洞里.在一条数轴上,一共有n个洞,位置分别在xi,能容纳vi只老鼠.一共有m只老鼠位置分别在Xi,要躲进洞里,问所有老鼠跑进洞里的距离总和最小是多少. 输入格 ...