\(\\\)

Description


其实这题才是正版的 Qtree3......

给定 \(n\) 个点,以 \(1\) 号节点为根的树,点有点权。

\(m\) 次询问 以 \(x\) 为根的子树内,点权第 \(k\) 小的 节点编号 是多少。

有多组测试数据,每组数据以 \(DONE\) 结尾。

  • \(n,m\le 10^5\)

\(\\\)

Solution


注意到一棵树的子树 \(DFS\) 序是连续的。

一遍 \(DFS\) 确定 \(DFS\) 序以及各个点的子树大小。

在 \(DFS\) 序上建主席树就可以了。

查子树查的其实就是 \((dfn[x]-1,dfn[x]+size[x]-1]\) 。

注意查的是点的编号,但是注意到点权两两不同,就可以离散化后记录每一个点权对应的节点编号了。

主席树注意空间 开成17倍成功RE

\(\\\)

Code


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100010
#define gc getchar
#define Rg register
#define mid ((l+r)>>1)
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,m,tot,hd[N],val[N],tmp[N],len; struct edge{int to,nxt;}e[N<<1]; inline void add(int u,int v){
e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
} int cnt,dfn[N],sz[N],vpos[N],pos[N]; void dfs(int u,int fa){
sz[u]=1;
dfn[u]=++cnt;
vpos[cnt]=val[u];
for(Rg int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa){dfs(v,u);sz[u]+=sz[v];}
} struct seg{ int rot[N],ptr; inline int newnode(){return ++ptr;} struct node{int ls,rs,sum;}c[N*20]; void build(int &rt,int l,int r){
rt=newnode();
if(l==r) return;
build(c[rt].ls,l,mid);
build(c[rt].rs,mid+1,r);
} inline void pushup(int rt){
c[rt].sum=c[c[rt].ls].sum+c[c[rt].rs].sum;
} void insert(int &rt,int lst,int l,int r,int x){
rt=newnode();
if(l==r){c[rt].sum=c[lst].sum+1;return;}
if(x<=mid){
c[rt].rs=c[lst].rs;
insert(c[rt].ls,c[lst].ls,l,mid,x);
}
else{
c[rt].ls=c[lst].ls;
insert(c[rt].rs,c[lst].rs,mid+1,r,x);
}
pushup(rt);
} inline int query(int rtl,int rtr,int l,int r,int k){
if(l==r) return l;
int nowans=c[c[rtr].ls].sum-c[c[rtl].ls].sum;
if(k<=nowans) return query(c[rtl].ls,c[rtr].ls,l,mid,k);
else return query(c[rtl].rs,c[rtr].rs,mid+1,r,k-nowans);
} }tree; int main(){
n=rd();
for(Rg int i=1;i<=n;++i) tmp[i]=val[i]=rd();
sort(tmp+1,tmp+1+n);
for(Rg int i=1;i<=n;++i){
tmp[++len]=tmp[i];
while(tmp[i+1]==tmp[i]) ++i;
}
for(Rg int i=1;i<=n;++i){
val[i]=lower_bound(tmp+1,tmp+1+len,val[i])-tmp;
pos[val[i]]=i;
}
for(Rg int i=1,u,v;i<n;++i){
u=rd(); v=rd(); add(u,v); add(v,u);
}
dfs(1,0);
tree.build(tree.rot[0],1,len);
for(Rg int i=1;i<=n;++i) tree.insert(tree.rot[i],tree.rot[i-1],1,len,vpos[i]);
m=rd();
for(Rg int i=1,rt,k;i<=m;++i){
rt=rd(); k=rd();
printf("%d\n",pos[tree.query(tree.rot[dfn[rt]-1],tree.rot[dfn[rt]+sz[rt]-1],1,len,k)]);
}
return 0;
}

[ SPOJ PT07J ] Query on a tree III的更多相关文章

  1. 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 ...

  2. SP1487 PT07J - Query on a tree III (主席树)

    SP1487 PT07J - Query on a tree III 题意翻译 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小 ...

  3. SPOJ 1487 Query on a tree III(划分树)

    题目链接:http://www.spoj.com/problems/PT07J/ 题意:给出一个有根树,1为根节点,每个节点有权值.若干询问,询问以u为根的子树中权值第K小的节点编号. 思路:DFS一 ...

  4. SP1487 PT07J - Query on a tree III 主席树+dfs序

    Code: #include<iostream> #include<cstdio> #include<algorithm> #include<string&g ...

  5. 【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 ...

  6. 「SPOJ1487」Query on a tree III

    「SPOJ1487」Query on a tree III 传送门 把树的 \(\text{dfs}\) 序抠出来,子树的节点的编号位于一段连续区间,然后直接上建主席树区间第 \(k\) 大即可. 参 ...

  7. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  8. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

  9. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

随机推荐

  1. win10笔记本相机打开黑屏无法打开笔记本相机

    打开注册表编辑器(WINDOWS图标+R,或者右击左下角微软图标选择“运行(R)”),在出现的窗口输入regedit并回车(Enter)确定   进入HKEY_LOCAL_MACHINE \ SOFT ...

  2. spring依赖注入中获取JavaBean

    一.这个接口有什么用? 当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean.换句话说,就是这个类可以 ...

  3. android的ListView点击item使item展开的做法

    直接上代码把.主要是又一次给item measure高度,直接上代码把 import java.util.ArrayList; import android.app.Activity; import ...

  4. Linux下,PHP的SESSION不起作用的问题

    改动SESSION目录的权限就能够了. 先找到SESSION目录, 然后 chmod -R 777 /var/lib/php/session 假设没有此目录,则新建此目录 mkdir -R 777 / ...

  5. Linux 命令修改系统时间

    修改linux的系统时间使用date指令,date命令的功能是显示和设置系统日期和时间. 输入date 查看目前系统时间. 修改时间需要 date -功能字符 修改内容 命令中各选项的含义分别为:-d ...

  6. Mac OS X 10.10, Eclipse+ADT真机调试代码时,Device Chooser中不显示真机的解决方式

    Mac OS X 10.10的环境下.Eclipse+ADT,进行真机调试时,会出现一个问题. Device Chooser对话框里不显示真机设备,仅仅有又一次插拔数据线才干够. 经过測试.有两个暂时 ...

  7. io口的作用

    I/O接口的作用     主机与外界交换信息称为输入/输出(I/O).主机与外界的信息交换是通过输入/输出设备进行的.一般的输入/输出设备都是机械的或机电相结合的产物,比方常规的外设有键盘.显示器.打 ...

  8. Python开发【第5节】【函数基础】

    1.函数 函数的本质就是功能的封装. 函数的作用 提升代码的重复利用率,避免重复开发相同代码 提高程序开发效率 便于程序维护 2.函数定义 def 函数名(参数): """ ...

  9. Java千百问_03基本的语法(001)_局部变量、类变量、实例变量有什么差别

    点击进入_很多其它_Java千百问 局部变量.类变量.实例变量有什么差别 在聊局部变量.类变量.实例变量有什么差别之前,我们须要了解一下Java变量. 1.Java变量是什么 在数学世界中,我们知道有 ...

  10. c++运算符重载以及一些基本概念

    c++primer第四版435 1.赋值( = ), 下标( [ ] ) ,调用 (  ( )  ), 成员訪问箭头 (->)等操作符必须定义为成员,定义为非成员时,编译器报错 2. 像赋值一样 ...