【BZOJ2588】Count on a tree 题解(主席树+LCA)
前言:其实就是主席树板子啦……只不过变成了树上的查询
--------------------------
题目大意:求树上$u$到$v$路径第$k$大数。
查询静态区间第$k$大肯定是用主席树。我们知道主席树有着优秀的性质:对于前缀和和树上差分等操作都是满足的。感性理解一下:我们在打主席树板子的时候,每次查询都是$query(rt[l-1],rt[r],1,len,k)$,然后$k$与$sum[ls[r]]-sum[ls[l-1]]$比较。所以在进行树上的询问时,我们只要把板子的操作换成$sum[u]+sum[v]-sum[lca]-sum[fa[lca]]$即可。建树的话根据$dfs$序遍历整颗树建立$n$颗权值线段树即可,顺便把树上结点的祖先结点也求了。我们就这样成功AC一道主席树板子题。
PS:一开始RE了,调试代码时发现是把$root$打成$tot$QAQ。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=;
int fa[maxn][],n,m,a[maxn],b[maxn],rt[maxn],tot,len,last,dep[maxn];
int ls[],rs[],sum[];
int head[],cnt;
struct node
{
int next,to;
}edge[];
inline int getpos(int x) {return lower_bound(b+,b+len+,x)-b;}
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
inline int build(int l,int r)
{
int root=++tot,mid=(l+r)>>;
if (l<r)
{
ls[root]=build(l,mid);
rs[root]=build(mid+,r);
}
return root;
}
inline int update(int k,int l,int r,int root)
{
int dir=++tot;
ls[dir]=ls[root],rs[dir]=rs[root];sum[dir]=sum[root]+;
int mid=(l+r)>>;
if (l<r)
{
if (k<=mid) ls[dir]=update(k,l,mid,ls[root]);
else rs[dir]=update(k,mid+,r,rs[root]);
}
return dir;
}
inline void dfs(int now,int f)
{
fa[now][]=f;dep[now]=dep[f]+;
for (int i=;i<=;i++) fa[now][i]=fa[fa[now][i-]][i-];
rt[now]=update(getpos(a[now]),,len,rt[f]);
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (to==f) continue;
dfs(to,now);
}
}
inline int LCA(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
for (int i=;i>=;i--)
if (dep[fa[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][];
}
inline int query(int u,int v,int f,int ff,int l,int r,int k)
{
if (l==r) return l;
int mid=(l+r)>>;
int x=sum[ls[u]]+sum[ls[v]]-sum[ls[f]]-sum[ls[ff]];
if (k<=x) return query(ls[u],ls[v],ls[f],ls[ff],l,mid,k);
else return query(rs[u],rs[v],rs[f],rs[ff],mid+,r,k-x);
}
inline int querypath(int u,int v,int k)
{
int lca=LCA(u,v);
return query(rt[u],rt[v],rt[lca],rt[fa[lca][]],,len,k);
}
signed main()
{
n=read(),m=read();
for (int i=;i<=n;i++) a[i]=read(),b[i]=a[i];
for (int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
sort(b+,b+n+);
len=unique(b+,b+n+)-b-;
rt[]=build(,len);
dfs(,);
for (int i=;i<=m;i++)
{
int u=read(),v=read(),k=read();
u=u^last;
printf("%lld\n",last=b[querypath(u,v,k)]);
}
return ;
}
【BZOJ2588】Count on a tree 题解(主席树+LCA)的更多相关文章
- [Bzoj2588]Count on a tree(主席树+LCA)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- Count on a tree 树上主席树
Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...
- BZOJ2588 SPOJ10628 Count on a tree 【主席树】
BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...
- 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 5217 Solved: 1233 ...
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】
算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...
随机推荐
- day20 函数收尾+面向过程+模块
目录 一.算法(二分法) 二.面向过程与函数式 1 编程范式/思想 2 面向过程 3 函数式 3.1 匿名函数与lambda 三.模块 1 什么是模块 2 为何要有模块 3 怎么用模块 3.1第一次导 ...
- Redis实例讲解
简介 Redis是一个key-value的nosql产品,和我们熟知的Memcached有些类似,但他存储value类型相对更加丰富,包括string(字符串),list(链表),set(集合),zs ...
- scala 数据结构(三):元组Tuple
1 元组Tuple-元组的基本使用 基本介绍 元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据. 说的简单点,就是将多个无关的数据封装为一个整体,称为元组, 最多的特点灵活,对数据没有过多 ...
- python--动态网页渲染pyqt5
原文:https://blog.csdn.net/tymatlab/article/details/78647543 PyQt5 渲染动态网页 示例代码: # -*- coding: UTF-8 -* ...
- 数据规整:连接、联合与重塑知识图谱-《利用Python进行数据分析》
所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片. 其他章 ...
- bzoj3442学习小组
bzoj3442学习小组 题意: 共有n个学生,m个学习小组,每个学生只愿意参加其中的一些学习小组,且一个学生最多参加k个学习小组.每个学生参加学习小组财务处都收一定的手续费,不同的学习小组有不同的手 ...
- elementui 使用Form表单 的 resetForm表单功能出现的问题
代码因为在保密机上,这里只进行描述并截取elemen文档中的代码作为参考 今天在开发一个很简单需求的时候遇到的问题,在使用elementui的表单功能,将增和改的表单进行了复用,是在表单的父组件 dr ...
- 软件测试工程师应该怎样规划自己?成为年薪30W+测试工程师(乾坤未定,皆是黑马)
今天在知乎上被邀了一个问题,软件测试工程师应该怎样规划自己?16年毕业,技术方面已经渣到不行,因为之前的公司没有Python自动化测试这个要求,有些迷茫.我把我的问题回答贴出来希望可以帮助到更多有类型 ...
- Go Pentester - TCP Scanner
Simple Port Scanner with Golang Use Go‘s net package: net.Dial(network, address string) package main ...
- CAS底层原理与ABA问题
CAS定义 CAS(Compare And Swap)是一种无锁算法.CAS算法是乐观锁的一种实现.CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当预期值A和内存值V相同时,将内存值V修 ...