主席树——树链上第k大spoj COT
首先要求第k大就想到用主席树来处理
但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护
那么久维护每个点到根节点的全值线段树,结点u的权值线段树记录了其到根节点路径上数值的出现次数
主席树相当于维护了一个前缀和,由树上前缀和可以分析出u->v路径上对应的那棵权值线段树应该是
T[u]+T[v]-T[lca]-T[fa[lca]]
所以只要在dfs过程中,结点u依赖fa[u]进行更新主席树即可
那么问题解变成了每个结点u上维护到root的权值线段树,然后每次询问求lca(u,v),再按照上述公式去主席树上查询第k大
求lca可以用树剖,也可以倍增。。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
const int N = 1e5+;
struct Node{int lc,rc,sum;}T[N*];
int fa[*N][], dep[*N], vis[N];
int a[N], b[N], tot, cnt, head[N], len;
struct node{int to, next;} p[*N];
void init(){
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
cnt=;
return ;
}
void add(int u,int v){
p[cnt].to=v,p[cnt].next=head[u];head[u]=cnt++;
p[cnt].to=u,p[cnt].next=head[v];head[v]=cnt++;
return ;
}
int size,rt[N];
int build(int l,int r){
int now=++size;
T[now].lc=T[now].rc=T[now].sum=;
if(l==r)return now;
int mid=l+r>>;
T[now].lc=build(l,mid);
T[now].rc=build(mid+,r);
return now;
} int update(int l,int r,int last,int pos){//更新到pos点
int now=++size;
T[now]=T[last];T[now].sum++;
if(l==r)return now;
int mid=l+r>>;
if(pos<=mid)T[now].lc=update(l,mid,T[last].lc,pos);
else T[now].rc=update(mid+,r,T[last].rc,pos);
return now;
}
int query(int e1,int e2,int s1,int s2,int l,int r,int k){
if(l==r)return l;
int mid=l+r>>;
int sum=T[T[e1].lc].sum+T[T[e2].lc].sum-T[T[s1].lc].sum-T[T[s2].lc].sum;
if(k<=sum)return query(T[e1].lc,T[e2].lc,T[s1].lc,T[s2].lc,l,mid,k);
else return query(T[e1].rc,T[e2].rc,T[s1].rc,T[s2].rc,mid+,r,k-sum);
} void dfs(int u,int d,int f,int root){
vis[u]=,dep[u]=d,fa[u][]=f;
rt[u]=update(,len,root,a[u]);
for(int i=head[u];i!=-;i=p[i].next){
int v=p[i].to;
if(vis[v]) continue;
dfs(v,d+,u,rt[u]);
}
} int f[maxn],son[maxn],d[maxn],siz[maxn];
void dfs1(int x,int pre,int deep){
f[x]=pre;siz[x]=;d[x]=deep;
for(int i=head[x];i!=-;i=p[i].next){
int y=p[i].to;
if(y==pre)continue;
dfs1(y,x,deep+);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]])son[x]=y;
}
}
int id[maxn],rk[maxn],idx,top[maxn];
void dfs2(int x,int tp){
top[x]=tp;id[x]=++idx;rk[idx]=x;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i!=-;i=p[i].next){
int y=p[i].to;
if(y!=son[x] && y!=f[x])dfs2(y,y);
}
}
int Query(int x,int y){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]])swap(x,y);
x=f[top[x]];
}
if(id[x]>id[y])swap(x,y);
return x;
} int main(){
int t, n, q;
scanf("%d %d", &n, &q);
for(int i=; i<=n; i++) scanf("%d", &a[i]), b[i]=a[i];
sort(b+,b+n+);
len=unique(b+,b+n+)-(b+);
tot=;
rt[]=build(,len);
for(int i=; i<=n; i++) a[i]=lower_bound(b+,b+len+,a[i])-(b);
init();
for(int i=;i<n-;i++){
int x, y;
scanf("%d %d", &x, &y);
add(x,y);
}
dfs(,,,rt[]);dfs1(,,),dfs2(,);
int ans=;
while(q--){
int l, r, x;
scanf("%d %d %d", &l, &r, &x);l^=ans;
int pos=Query(l,r);
printf("%d\n",ans=b[query(rt[l],rt[r],rt[pos],rt[fa[pos][]],,len,x)]);
}
return ;
}
主席树——树链上第k大spoj COT的更多相关文章
- 树上主席树 - 查询树链上第K大
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- HDU 5249 离线树状数组求第k大+离散化
KPI Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 可持久化线段树(主席树)——静态区间第k大
主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...
- 主席树 - 查询某区间第 K 大
You are working for Macrohard company in data structures department. After failing your previous tas ...
- 洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大
我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上. Code: #include<cstdio> #include<cs ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
- 主席树入门——询问区间第k大pos2104,询问区间<=k的元素个数hdu4417
poj2104找了个板子..,但是各种IO还可以进行优化 /* 找区间[l,r]第k大的数 */ #include<iostream> #include<cstring> #i ...
- 【大杀器】利用划分树秒杀区间内第k大的数
最近看了一道题,大概就是给出一个序列,不断询问其子区间内第k大的数,下面是个截图 绕了一圈没找到中文版题目,if(你是大佬) then 去看截图:else{我来解释:给出一个整数n,和一个整数m,分别 ...
- POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8807 Accepted ...
随机推荐
- C语言博客作业02--循环结构
1.本章学习总结 1.1 思维导图 1.2 本章学习体会及代码量学习体会 1.2.1 学习体会 经过本周学习,对c循环结构有了深入,无论是单层循环结构还是嵌套循环结构的问题,我都学会有一定的解决能力, ...
- rpm打包要点
1. 查看变量: rpmbuild --showrc 2. spec文件 头部 多行的部分,如 %changelog 或 %description 由指令下一行开始,空行结束.一些不需要的行 (如 B ...
- 20165223《网络对抗技术》Exp0 Kali的安装
(1)安装步骤 Kali官网,下载Kali Linux 64 bit版本,按照网上安装教程进行即可 我是直接拷贝了Kali的.vmx文件(Linux 64bit),在上学期已经安装好的VMware中可 ...
- 互联网+ 何人能挡?带着你的Code飞奔吧!
Python方向: 早期方向 Web全栈 擅长专栏 爬虫系列 数据分析 人工智能 物联网系(lot万物互联)[逆天很看好未来的前景] 自动化运维(安全与测试) 其他系列 游戏开发(最近很火) 导航栏: ...
- iOS开发,这样写简历才能让大厂面试官看重你!
前言: 对于职场来说,简历就如同门面.若是没想好,出了差错,耽误些时日倒不打紧,便是这简历入不了HR的眼,费力伤神还不能觅得好去处,这数年来勤学苦练的大好光阴,岂不辜负? 简历,简而有力.是对一个人工 ...
- Borůvka algorithm
Borůvka algorithm 我好无聊啊,直接把wiki的算法介绍翻译一下把. wiki关于Borůvka algorithm的链接:链接 Borůvka algorithm是一个在所有边权都是 ...
- mac-redis安装与使用
安装: brew install redis --------------- 使用: 启动redis-server: sudo redis-server 连接:./redis-cli -h 127.0 ...
- (三) 查看USB设备
目录 查看USB设备 lsusb ll /sys/bus/usb/devices cat /sys/kernel/debug/usb/devices dmesg title: 查看USB设备 date ...
- jQuery实现搜索框插件+豆瓣音乐接口实现豆瓣搜索框
jQuery实现搜索框插件 豆瓣音乐接口实现豆瓣搜索框 豆瓣接口有时不稳定,网络请求会报400,不要惊慌.我主要是练习一下jQuery的JSONP和封装插件. <div class=" ...
- linux下安装svn1.7
转自 https://blog.csdn.net/u011752559/article/details/11559573?locationNum=11&fps=1 1.下载svn安装包 wge ...