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, ...
随机推荐
- [BZOJ1339] [Baltic2008] Mafia / 黑手党
Description 匪徒准备从一个车站转移毒品到另一个车站,警方准备进行布控. 对于每个车站进行布控都需要一定的代价, 现在警方希望使用最小的代价控制一些车站,使得去掉这些车站后,匪徒无法从原定的 ...
- [bzoj3004] [SDOi2012]吊灯
Description Alice家里有一盏很大的吊灯.所谓吊灯,就是由很多个灯泡组成.只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的.也就是说,整个吊灯实际上类似于[b]一棵树[/b ...
- [WC2007]剪刀石头布——费用流
比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...
- 【BZOJ 2432】 [Noi2011]兔农 矩乘+数论
这道题的暴力分还是很良心嘛~~~~~ 直接刚的话我发现本蒟蒻只会暴力,矩乘根本写不出来,然后让我们找一下规律,我们发现如果我们把这个序列在mod k的意义下摆出,并且在此过程中把值为1的的数减一,我们 ...
- 【BZOJ 1124】[POI2008] 枪战Maf Tarjan+树dp
#define int long long using namespace std; signed main(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...
- COGS 930. [河南省队2012] 找第k小的数 主席树
主席树裸板子 #include<cstdio> #include<iostream> #include<algorithm> #define MAXN 100005 ...
- 压缩跟踪Compressive Tracking
好了,学习了解了稀疏感知的理论知识后,终于可以来学习<Real-Time Compressive Tracking>这个paper介绍的感知跟踪算法了.自己英文水平有限,理解难免出错,还望 ...
- 关于session variables 和 global variables
背景 有同学问到这样一个问题:原来的binlog格式是statement,为什么执行了 set global binlog_format='row' 和 set binlog_format='row' ...
- arraylist和array的不同之处
https://www.cnblogs.com/wangbin2188/p/6524200.html
- es6+最佳入门实践(7)
7.set和map数据结构 7.1.什么是set? Set就是集合,集合是由一组无序且唯一的项组成,在es6中新增了set这种数据结构,有点类似于数组,但是它的元素是唯一的,没有重复 let st = ...