题意翻译

给你一棵有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. flex兼容问题

    display:flex作为C3的新属性,还是有的浏览器不支持的,那下面我们就来说一下他的兼容写法 .box{ display: -webkit-box; /* 老版本语法: Safari, iOS, ...

  2. 小程序swiper实现订单页面

    小程序swiper实现订单页面 myOrder.wxml <!--pages/myorder/myorder.wxml--> <view class="swiper-tab ...

  3. JPA Hibernate 等面向对象持久化框架难以解决的问题

    1+N查询性能问题 单个更新实体对象,而不是使用单调语句 在Java端做了很重的数据处理,数据库端反而很少 多层次 fetch inner join 难以实现 关联映射难以自定义条件 级联操作难以掌控 ...

  4. UVALive 6855 Banks (暴力)

    Banks 题目链接: http://acm.hust.edu.cn/vjudge/contest/130303#problem/A Description http://7xjob4.com1.z0 ...

  5. [CF46D]Parking Lot

    题目:Parking Lot 传送门:http://codeforces.com/problemset/problem/46/D 分析: 做法一: 1)这题和Hotel那题一样,也可以看做是求区间空位 ...

  6. VMware Workstation 14 Pro安装教程(详细)

    VMware Workstation 14 Pro安装教程(详细) 话不多说,直接上图,需要的拿走. 下载地址:https://download3.vmware.com/software/wkst/f ...

  7. datatbales的数据源类型(Data source types)

    数据是复杂的,并且所有的数据是不一样的.因此 DataTables 中有很多的选项可用于配置如何获得表中的数据显示,以及如何处理这些复杂的数据. 本节将讨论 DataTables 处理数据的三个核心概 ...

  8. Linux内核调试方法总结之Call Trace

    内核态call trace 内核态有三种出错情况,分别是bug, oops和panic. bug属于轻微错误,比如在spin_lock期间调用了sleep,导致潜在的死锁问题,等等. oops代表某一 ...

  9. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_01 Collection集合_2_集合框架介绍

  10. java 泛型深入

    1.<? extends E> <? extends E> 是 Upper Bound(上限) 的通配符,用来限制元素的类型的上限.   赋值 List<? extend ...