主席树——树链上第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 ...
随机推荐
- Frame Interpolation
对于视频网站.电视厂商以及进行视频压制的用户来说,改变视频的帧率算是一个比较常见的需求.视频网站改变帧率主要是为了向不同级别的网站用户提供差异化服务:电视厂商则是以提供更好的显示效果作为电视的卖点:对 ...
- laravel 【error】MethodNotAllowedHttpException No message
Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException No message 报错原因[原理]CSRF ...
- Mysql 查询当月时间数据
SELECTDATE_FORMAT(CURDATE(), '%Y%m'), DATE_FORMAT(t.transactiontime, '%Y%m'),t.*FROM ttransactions t ...
- Java基础 -- Collection和Iterator接口的实现
Collection是描述所有序列容器(集合)共性的根接口,它可能被认为是一个“附属接口”,即因为要表示其他若干个接口的共性而出现的接口.另外,java.util.AbstractCollection ...
- Inheritance: 'A' is an inaccessible base of 'B'
'boost::enable_shared_from_this<net::Session>' is an inaccessible base of 'net::Session' BOOST ...
- 20175209 实验二《Java面向对象程序设计》实验报告
20175209 实验二<Java面向对象程序设计>实验报告 一.实验前期准备 了解三种代码 伪代码 产品代码 测试代码 我们先写伪代码,伪代码 从意图层面来解决问题: 有了伪代码 我们用 ...
- codeforces-1142 (div1)
div1真难,现在就是后悔, 非常后悔 A.显然如果我们知道起点和终点是哪两个点,我们可以算出距离通过b / gcd(a,b)的方式求出需要走几步的. 并且数据范围似乎也允许我们这么做,所以直接枚举取 ...
- (三) 查看USB设备
目录 查看USB设备 lsusb ll /sys/bus/usb/devices cat /sys/kernel/debug/usb/devices dmesg title: 查看USB设备 date ...
- GIT-Linux(CentOS7)系统部署git服务器
GIT-Linux(CentOS7)系统部署git服务器 root账号登录 一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget ...
- iTOP-iMX6UL开发板【全能版】-动态调频技术简介
本文档以 iMX6UL 为例,简单介绍 cpufreq 的 5 种模式. 在 imx6ul 的 menuconfig 中,进入 CPU Power Management ---> CPU Fre ...