BZOJ2588 树上静态第k大
题意翻译
给你一棵有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大的更多相关文章
- 划分树 静态第k大
划分树是保存了快速排序的过程的树,可以用来求静态第k小的数 如果,划分树可以看做是线段树,它的左孩子保存了mid-L+1 个 小于等于 a[mid] 的数字, 右孩子保存了 R-mid个大于等于a[ ...
- 主席树(可持久化线段树) 静态第k大
可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域 ...
- POJ 2104:K-th Number(主席树静态区间k大)
题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...
- [TS-A1505] [清橙2013中国国家集训队第二次作业] 树 [可持久化线段树,求树上路径第k大]
按Dfs序逐个插入点,建立可持久化线段树,每次查询即可,具体详见代码. 不知道为什么,代码慢的要死,, #include <iostream> #include <algorithm ...
- 主席树套树状数组——带修区间第k大zoj2112
主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...
- 主席树——树链上第k大spoj COT
首先要求第k大就想到用主席树来处理 但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护 那么久维护每个点到根节点的全值线段树,结点u的权值线段树 ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
- 可持久化线段树(主席树)——静态区间第k大
主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...
- 数据结构2 静态区间第K大/第K小
给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...
随机推荐
- winXP 系统下ubuntu-12.04 硬盘安装
目地:实现XP ubuntu双系统,引导可选择. 出处:根查阅网络资料和自己的安装体检,记录如是. 系统版本:windowsXP SP3 Ubuntu 12.04 工具资源:grup4dos 2 ...
- 运行job检验单元测试覆盖率
http://ns.jenkins.baidu.com/user/anyixing/my-views/view/Map_ut/job/poi-zhunru/ 1在http://ns.jenkins.b ...
- yum命令查询详解
一.列举包文件列出资源库中所有可以安装或更新的rpm包# yum list列出资源库中特定的可以安装或更新以及已经安装的rpm包# yum list perl //列出名为perl ...
- 【后台管理系统】—— Ant Design Pro页面相关(一)
一.List列表形式 import React, { PureComponent } from 'react'; import { findDOMNode } from 'react-dom'; im ...
- Ehrenfeucht–Fraïssé game back-and-forth games
w https://en.wikipedia.org/wiki/Ehrenfeucht–Fraïssé game
- c# access oledb helper class
连接Access数据库 using System; using System.Collections.Generic; using System.Linq; using System.Text; us ...
- JS-Proxy
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等). 参考:Proxy - JavaScript | MDN 语法: let p = new Proxy(target, ...
- Linux_VMWare12 Install RHEL7
目录 目录 前言 Install RHEL7 前言 准备考试,顺便来一波VMWare安装虚拟机的图文详解. Install RHEL7 step1. 选择自定义安装,Next step2. 版本兼容性 ...
- struts2 token 防止表单重复提交
1.jsp页面 输入框,提交按钮 <%@ page language="java" contentType="text/html" pageEncodi ...
- python笔记01(详情请看廖雪峰的官方网站)
python 在调用函数的时候, 如果传入的参数数量不对, 如果传入的参数类型不对 会报TypeError的错误,并且Python会明确提示参数错误原因. hex()内置函数会把一个整数转换成十六进制 ...