题意翻译

给你一棵有n个结点的树,节点编号为1~n。

每个节点都有一个权值。

要求执行以下操作:

U V K:求从节点u到节点v的第k小权值。

输入输出格式

输入格式

第一行有两个整数n和m(n,m≤100000) 第二行有n个整数。 第i个整数表示第i个节点的权值。

接下来的n-1行中,每行包含两个整数u v,表示u和v之间有一条边。

接下来的m行,每行包含三个整数U V K,进行一次操作。

输出格式

对于每个操作,输出结果。

解题思路:和序列上的静态主席树差不多

我们先想序列上的做法。对于一个位置i,先令root[i]=root[i-1],然后再在root[i里面插入a[i]。这样每一个位置实际上维护了[1,n]的信息。
同理,放到树上,对于一个节点i,先令root[i]=root[fa[i]],然后再在root[i]里面插入a[i]。这样每一个位置实际上维护了这个节点到根的信息。
查询的时候,对于序列上的情况,我们只需要用root[r]-root[l-1],就可以得到需要的信息了。
放到树上,对于一个询问(u,v),我们需要用root[u]+root[v]-root[lca]-root[fa[lca]],得到需要的信息。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=;
int n,m,sz,a[maxn],head[maxn],fa[maxn][],dep[maxn],cnt,tot,root[maxn*];
struct node{
int l,r,sum;
}T[maxn*];
vector<int> v;
struct Edge{
int u,v,next;
}edge[maxn*];
void add(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int getid(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+;
}
void update(int l,int r,int &x,int y,int pos){
T[++cnt]=T[y],T[cnt].sum++,x=cnt;
if(l==r) return;
int mid=(l+r)/;
if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos);
else update(mid+,r,T[x].r,T[y].r,pos);
}
void dfs(int u,int pre){
dep[u]=dep[pre]+;
fa[u][]=pre;
for(int i=;i<=;i++)
fa[u][i]=fa[fa[u][i-]][i-];
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(v==pre) continue;
update(,sz,root[v],root[u],getid(a[v]));
dfs(v,u);
}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=;i>=;i--){
if(dep[x]-(<<i)>=dep[y]) x=fa[x][i];
}
if(x==y) return x;
for(int i=;i>=;i--){
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
}
return fa[x][];
}
int query(int l,int r,int x,int y,int lc,int flc,int k){
if(l==r) return l;
int mid=(l+r)/,sum=;
sum=T[T[x].l].sum+T[T[y].l].sum-T[T[lc].l].sum-T[T[flc].l].sum;
if(k<=sum) return query(l,mid,T[x].l,T[y].l,T[lc].l,T[flc].l,k);
else return query(mid+,r,T[x].r,T[y].r,T[lc].r,T[flc].r,k-sum);
}
int main(){
scanf("%d%d",&n,&m);
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
sz=v.size();
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
update(,sz,root[],root[],getid(a[]));
dfs(,);
for(int i=;i<=m;i++){
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
int lc=lca(x,y);
printf("%d\n",v[query(,sz,root[x],root[y],root[lc],root[fa[lc][]],k)-]);
}
return ;
}

BZOJ2588 树上静态第k大的更多相关文章

  1. 划分树 静态第k大

    划分树是保存了快速排序的过程的树,可以用来求静态第k小的数 如果,划分树可以看做是线段树,它的左孩子保存了mid-L+1 个 小于等于 a[mid] 的数字,  右孩子保存了 R-mid个大于等于a[ ...

  2. 主席树(可持久化线段树) 静态第k大

    可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域 ...

  3. POJ 2104:K-th Number(主席树静态区间k大)

    题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...

  4. [TS-A1505] [清橙2013中国国家集训队第二次作业] 树 [可持久化线段树,求树上路径第k大]

    按Dfs序逐个插入点,建立可持久化线段树,每次查询即可,具体详见代码. 不知道为什么,代码慢的要死,, #include <iostream> #include <algorithm ...

  5. 主席树套树状数组——带修区间第k大zoj2112

    主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...

  6. 主席树——树链上第k大spoj COT

    首先要求第k大就想到用主席树来处理 但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护 那么久维护每个点到根节点的全值线段树,结点u的权值线段树 ...

  7. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  8. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  9. 数据结构2 静态区间第K大/第K小

    给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...

随机推荐

  1. SSH 连接慢 等好久

    SSH连接慢,要等好久好久,有时出现输入密码提示符,输入密码回车立即就超时了. ssh -v xxx.xxx.xxx.xxx   看到是GSS的问题. 解决办法,在两边SSH上配置,UseDNS如果被 ...

  2. str_pad()函数

    str_pad - 使用另一个字符串填充字符串为指定长度   <?php $str = 'hello world '; echo str_pad($str,20,'·'); ?>   结果 ...

  3. ERROR 1366 (HY000): Incorrect string value:MySQL数据库、表的字符集为GBK

    mysql> update userinfo set MEDIASOURCE = 'CS02-北京' where IMPORTNO = 'IMP201640613101206';ERROR 13 ...

  4. 架构-层-DAL:DAL

    ylbtech-架构-层-DAL:DAL DAL是数据访问层的英文缩写,即为数据访问层(Data Access Layer).其功能主要是负责数据库的访问.简单地说就是实现对数据表的Select(查询 ...

  5. Eclipse Java工程转为Web工程步骤

    找到工程的.project文件,在<natures>标签中增加以下两行配置:<nature>org.eclipse.wst.common.modulecore.ModuleCo ...

  6. VMware 虚拟机的虚拟磁盘编程知识点扫盲之二

    目录 目录 前文列表 VDDK 安装 VDDK VixDiskLib VADP 前文列表 VMware 虚拟机的虚拟磁盘编程知识点扫盲之一 VDDK 摘自官方文档:The Virtual Disk D ...

  7. IDE(Pycharm&&IDEA)配置文件模版

    Pycharm ====> 修改Python Script : 修改位置:Edito >> File and CodeTemplates >> Python Script ...

  8. dvorak键盘布局调整

    一站直达: http://www.kaufmann.no/roland/dvorak/

  9. Node.js实战11:fs模块初探。

    fs模块封装了对文件操作的各种方法,比如同步和异步读写.批量操作.流.监听. 我们还是通常例程学习, 获取目录下的文件清单: var fs =require("fs"); fs.r ...

  10. jmeter分布式压测 java.io.FileNotFoundException: rmi_keystore.jks (系统找不到指定的文件。)

    解决办法:1.控制机和代理机:修改jmeter.properties中server.rmi.ssl.disable=true 不启动SSL2.控制机和代理机: Slave(从压力机)启动jmeter- ...