☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\)
传送门:>Here<
题意:给出一棵树。每个节点有点权。问某一条路径上排名第\(K\)小的点权是多少
解题思路
类似区间第\(K\)小,但放在了树上。
考虑维护一棵主席树,其中每棵权值线段树维护从一个节点\(i\)到根节点上每个点权的出现次数(点权先离散化)。于是我们可以
得到\((u,v)\)之间的路径上,某一权值的出现次数为$$sum[u]+sum[v]-sum[lca]-sum[fa[lca]]$$于是就很简单了
那么我们要按照什么顺序来进行\(update\)呢?由于我们要维护的是\(u\)到根节点上的所有点,如果想像正常主席树一样在另一个主
席树的基础上进行单点更新,那么这个点只能是它的父亲。于是我们要以\(dfs\)的顺序进行更新。
Code
/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 100010;
const int MAXM = 200010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = 0; int w = 1; register char c = getchar();
for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
if(c == '-') w = -1, c = getchar();
for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
struct Num{
int val,rnk,idx;
}a[MAXN];
int N,M,x,y,k,lastans,lca;
int first[MAXM],nxt[MAXM],to[MAXM],cnt;
int dep[MAXN],f[MAXN][25],T[MAXN],mp[MAXN];
struct zxs{
int ls[MAXN<<5],rs[MAXN<<5],sum[MAXN<<5],numNode;
int update(int pre, int l, int r, int x){
int cur = ++numNode;
ls[cur] = ls[pre], rs[cur] = rs[pre], sum[cur] = sum[pre] + 1;
if(l<r){
int mid = (l+r)/2;
if(x <= mid) ls[cur] = update(ls[pre], l, mid, x);
else rs[cur] = update(rs[pre], mid+1, r, x);
}
return cur;
}
int query(int u, int v, int lca, int flca, int l, int r, int k){
int amt = sum[ls[u]]+sum[ls[v]]-sum[ls[lca]]-sum[ls[flca]];
if(l>=r) return mp[l];
int mid = (l+r)/2;
if(amt >= k) return query(ls[u],ls[v],ls[lca],ls[flca],l,mid,k);
else return query(rs[u],rs[v],rs[lca],rs[flca],mid+1,r,k-amt);
}
}qxz;
inline bool cmp1(const Num& a, const Num& b){ return a.val < b.val; }
inline bool cmp2(const Num& a, const Num& b){ return a.idx < b.idx; }
inline void add(int u, int v){
to[++cnt]=v, nxt[cnt]=first[u], first[u]=cnt;
}
void lca_dfs(int u, int Fa, int d){
dep[u] = d;
f[u][0] = Fa;
for(int i = 1; (1 << i) <= d; ++i){
f[u][i] = f[f[u][i-1]][i-1];
}
int v;
for(int i = first[u]; i; i = nxt[i]){
if((v = to[i]) == Fa) continue;
T[v] = qxz.update(T[u], 1, N, a[v].rnk);
lca_dfs(v, u, d+1);
}
}
inline int getLca(int a, int b){
if(dep[a] < dep[b]) swap(a, b);
for(int i = 20; i >= 0; --i){
if(dep[a] - (1<<i) < dep[b]) continue;
a = f[a][i];
}
if(a == b) return a;
for(int i = 20; i >= 0; --i){
if(f[a][i] == f[b][i]) continue;
a = f[a][i], b = f[b][i];
}
return f[a][0];
}
int main(){
// freopen(".in","r",stdin);
N = read(), M = read();
for(int i = 1; i <= N; ++i){
a[i].val = read();
a[i].idx = i;
}
sort(a+1, a+N+1, cmp1);
for(int i = 1; i <= N; ++i){
if(i != 1 && a[i].val == a[i-1].val) a[i].rnk = a[i-1].rnk;
else a[i].rnk = i;
}
sort(a+1, a+N+1, cmp2);
for(int i = 1; i <= N; ++i) mp[a[i].rnk] = a[i].val;
for(int i = 1; i < N; ++i){
x = read(), y = read();
add(x, y);
add(y, x);
}
T[1] = qxz.update(0, 1, N, a[1].rnk);
lca_dfs(1, 0, 1);
for(int i = 1; i <= M; ++i){
x = read(), y = read(), k = read();
x = x ^ lastans;
lca = getLca(x, y);
lastans = qxz.query(T[x],T[y],T[lca],T[f[lca][0]],1,N,k);
printf("%d\n", lastans);
}
return 0;
}
☆ [洛谷P2633] Count on a tree 「树上主席树」的更多相关文章
- 洛谷 P2633 Count on a tree
P2633 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中last ...
- 【洛谷2633】Count on a tree(树上主席树)
点此看题面 大致题意: 给你一棵树,每次问你两点之间第\(k\)小的点权,强制在线. 主席树 这种题目强制在线一般就是数据结构了. 而看到区间第\(k\)小,很容易就能想到主席树. 至少不会有人想到树 ...
- 洛谷P2633 Count on a tree(主席树上树)
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷P2633 Count on a tree
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- 洛谷 P2633 Count on a tree 主席树
在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$ ,建立 $i$ 到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...
- 洛谷 P2633 Count on a tree 题解
题面 对于每个点建立一颗主席树: 然后按照树上差分的思想统计主席树的前缀和: lca+主席树+前向星存表就可以了: #include <bits/stdc++.h> #define inc ...
- BZOJ2588 Count on a tree 【树上主席树】
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Submit: 7577 Solved: 185 ...
随机推荐
- 使用ArcGIS Earth矢量化高精度的数据(kml转图层转shp/要素类)
大家好,这次来分享干货.做地理分析的同学,或者需要使用地图却不知道哪里有精度较高矢量数据(如校园图)的时候,怎么办呢? 我们知道ArcGIS提供了精度较高的全球影像图,基于此,可以自己进行矢量化,然后 ...
- 用WijmoJS搭建您的前端Web应用 —— React
前文回顾 在本系列文章中,我们已经介绍了Angular和Vue框架下 WijmoJS 的玩法. 而今天,我们将展示如何使用 WijmoJS 来搭建一款具备独特创新性.出色性能和简单代码逻辑的 Reac ...
- Android 启动APP时黑屏白屏的解决方案
在开发中,我们在启动app的时候,屏幕会出现一段时间的白屏或者黑屏,不同设备时间长短不同.很影响用户体验. 首先分析一下,产生这个现象的原因,当我们在启动一个应用时,系统会去检查是否已经存在这样一个进 ...
- selenium-获取元素属性(六)
获取元素属性很简单,使用 get_attribute 方法即可 如下图 获取具体的属性直接将该属性名当作参数传入即可 若是获取值,则获取的实则是该元素的 value,需要将 value 当参数传入 i ...
- ServiceStack.Redis连接阿里云redis服务时使用连接池出现的问题
创建连接池 private static PooledRedisClientManager prcm = CreateManager(new string[] { "password@ip: ...
- LV 指定或修改逻辑卷的major, minor号[RHEL6]
在创建逻辑卷时,可以指定逻辑卷的major和minor设备号. [-M|--persistent {y|n}] //Set to y to make the minor number specifie ...
- Windows Server 2012 R2 配置FTP服务器
Windows Server 2012 R2 安装IIS参考上一篇配置IIS 8.0:https://www.cnblogs.com/aq-ry/p/9329310.html 搭建完IIS 后,最近又 ...
- Jenkins+VS项目持续集成
软件安装 安装包下载连接:https://jenkins.io/download/ 安装步奏:略 账户名:admin 密码:C:\Program Files (x86)\Jenkins\secrets ...
- QQ的孤独
接触网络到现在,已是好多年前的事了.初识网络犹如初恋般,充满了新鲜和好奇,于是,从聊天室到QQ,MSN,邮箱,再去BBS.然后有了博客^^^^^^ 那时的网络于我是那般充满诱惑,整天穿梭其中,乐此不彼 ...
- java 下载word freemaker
网上有很多优质的博文了,这里这篇博客就是记录一下字自己,写demo的历程,坑和收获 在java程序中下载word 有6中方式,此处省略(嘻嘻),不过大家公认的是 freemaker 和 PageOff ...