首先要求第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的更多相关文章

  1. 树上主席树 - 查询树链上第K大

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  2. HDU 5249 离线树状数组求第k大+离散化

    KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  3. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  4. 主席树 - 查询某区间第 K 大

    You are working for Macrohard company in data structures department. After failing your previous tas ...

  5. 洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大

    我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上. Code: #include<cstdio> #include<cs ...

  6. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  7. 主席树入门——询问区间第k大pos2104,询问区间<=k的元素个数hdu4417

    poj2104找了个板子..,但是各种IO还可以进行优化 /* 找区间[l,r]第k大的数 */ #include<iostream> #include<cstring> #i ...

  8. 【大杀器】利用划分树秒杀区间内第k大的数

    最近看了一道题,大概就是给出一个序列,不断询问其子区间内第k大的数,下面是个截图 绕了一圈没找到中文版题目,if(你是大佬) then 去看截图:else{我来解释:给出一个整数n,和一个整数m,分别 ...

  9. POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]

    The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted ...

随机推荐

  1. 关于flex布局【转】

    很受用,原文链接:http://blog.csdn.net/magneto7/article/details/70854472

  2. P1238 走迷宫

    原题链接 https://www.luogu.org/problemnew/show/P1238 为了巩固一下刚学习的广搜,练一下迷宫类型的题 不过这道题我用的深搜..... 看问题,我们就知道这道题 ...

  3. 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution

    对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...

  4. 【CSA35G】【XSY3318】Counting Quests DP 拉格朗日反演 NTT

    题目大意 zjt 是个神仙. 一天,zjt 正在和 yww 玩猜数游戏. zjt 先想一个 \([1,n]\) 之间的整数 \(x\),然后 yww 开始向他问问题. yww 每次给 zjt 一个区间 ...

  5. 使用apidoc生成项目文档

    [1]npm install apidoc -g 全局安装apidoc [2]apidoc -v 查看是否安装成功 [3]apidoc.json apidoc的项目级配置文件,它必须位于整个工程目录顶 ...

  6. 洛谷P5289 [十二省联考2019]皮配(01背包)

    啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...

  7. centos7使用kubeadm安装部署kubernetes 1.14

    应用背景: 截止目前为止,高热度的kubernetes版本已经发布至1.14,在此记录一下安装部署步骤和过程中的问题排查. 部署k8s一般两种方式:kubeadm(官方称目前已经GA,可以在生产环境使 ...

  8. EF Code First关系规则及配置

    1.一对多关系 关系表: Category 分类表 Product 产品表 分类与产品之间的一对多关系 1>.产品实体类不指定外键属性 Domain中类定义: Category.cs 1 usi ...

  9. 第十一节:WebApi的版本管理的几种方式

    一. 背景和方案 1. 多版本管理的概念 Android .IOS等 App 存在着多版本客户端共存的问题:App 最新版已经升级到了5.0 了,但是有的用户手机上还运行着 4.8.3.9 甚至2.2 ...

  10. i-83.net quadhost子产品

    i-83.net 6$一年, 首年半价, 优惠码: APR19-NAT50 加拿大 ---------------------------------------------------------- ...