题意翻译

给你一棵有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. java导入ldif文件

    网上导入ldif文件的方式都是基于命令,或者相应工具如LDAP Browser \Editor v2.8.2. 但用java去实现这样的功能好像网上很少,于是我参照相应的开源代码并整理了一下,亲自测试 ...

  2. Linux shell】grep命令精确匹配字符串查找

    需求: 精确匹配查找某个字符串   精确匹配: 例如: 在抽取字符串“48”,返回结果包含诸如484和483等包含“48”的其他字符串,实际上应精确抽取只包含48的各行. 使用grep抽取精确匹配的一 ...

  3. buildroot

    http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2 简介 buildroot是一个Makefiles和 ...

  4. xargs -i参数详解

    学习所需,文章转载过来! xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如 # find . -type f -name "*.log" | xa ...

  5. MySQL高可用方案 MHA之四 keepalived 半同步复制

    主从架构(开启5.7的增强半同步模式)master: 10.150.20.90   ed3jrdba90slave: 10.150.20.97    ed3jrdba97 10.150.20.132 ...

  6. principal components analysis 主成份分析

    w http://deeplearning.stanford.edu/wiki/index.php/主成份分析 主成分分析(PCA)及其在R里的实现 - jicf的日志 - 网易博客  http:// ...

  7. MySQL与MongoDB的不同

    数据存放的巨大不同

  8. 三十二、python操作XML文件

    '''XML:模块 xml总结 1.解析 str 文件 tree,ElementTree,type root,Element,type2.操作 Element: tag,text,find,iter, ...

  9. 安装fedora23后的一些杂项设置

    Boxes是创建虚拟机的技术 tweak: 拧, 捏; 微调 he gave the boy's ear a painful tweak. it's a small tweak over the ra ...

  10. 关于.NET Core的一些问题和疑惑

    1 为什么会出现.NET Core这个东西?即它为了解决什么问题. .NET Core是NET的ECMA标准的一种新的实现.目前.NET已有Framework,Mono,Unity等实现. 原先所有的 ...