Count on a tree 树上主席树

给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线

求解区间静态第\(k\)小即用主席树。

树上主席树类似于区间上主席树,我们利用前缀和相减获得区间的信息,树上主席树也是这样,维护一个到根节点的前缀和。对于\((u,v)\)路径,\(sum[u]+sum[v]-sum[lca(u,v)]-sum[fa[lca(u,v)]]\)即可获得树上\(u,v\)路径的区间信息,然后按照区间查询即可。

#include <cstdio>
#include <algorithm>
#define MAXN 1001000
#define MAXM MAXN*30
#define LOG 30
int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot;
inline void add_edge(int u, int v){
vv[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int n,m,s,cnt;
int f[MAXN][31],dep[MAXN];
int rot[MAXN];
int val[MAXN],idx[MAXN];
int tre[MAXM],sl[MAXM],sr[MAXM];
void build_tre(int &x, int l, int r){
x=++cnt;
if(l==r) return;
int mid=(l+r)>>1;
build_tre(sl[x], l, mid);
build_tre(sr[x], mid+1, r);
}
void change(int &x, int pre, int l, int r, int pos){
if(x==0) x=++cnt;
tre[x]=tre[pre]+1;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) change(sl[x], sl[pre], l, mid, pos),sr[x]=sr[pre];
else change(sr[x], sr[pre], mid+1, r, pos),sl[x]=sl[pre];
}
int query(int x, int y, int t, int tf, int l, int r, int k){
if(l==r) return l;
int mid=(l+r)>>1;
int tmp=tre[sl[x]]+tre[sl[y]]-tre[sl[t]]-tre[sl[tf]];
if(tmp>=k) return query(sl[x], sl[y], sl[t], sl[tf], l, mid, k);
else return query(sr[x], sr[y], sr[t], sr[tf], mid+1, r, k-tmp);
}
void dfs(int u, int fa){
f[u][0]=fa;
dep[u]=dep[fa]+1;
change(rot[u], rot[fa], 1, s, idx[u]);
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
dfs(v, u);
}
}
namespace lca{
void init(){
for(int i=1;i<=LOG;++i)
for(int j=1;j<=n;++j)
f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int a, int b){
if(dep[a]<dep[b]) std::swap(a,b);
for(int i=LOG;i>=0;--i)
if(dep[f[a][i]]>=dep[b])
a=f[a][i];
if(a==b) return a;
for(int i=LOG;i>=0;--i)
if(f[a][i]!=f[b][i]){
a=f[a][i];
b=f[b][i];
}
return f[a][0];
}
}
inline int read(){
char ch=getchar();int s=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s;
}
int val_sort[MAXN];
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i) val_sort[i]=val[i]=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
add_edge(x, y);add_edge(y, x);
}
std::sort(val_sort+1, val_sort+1+n);
s=std::unique(val_sort+1, val_sort+1+n)-val_sort;
for(int i=1;i<=n;++i)
idx[i]=std::lower_bound(val_sort+1, val_sort+1+s, val[i])-val_sort;
build_tre(rot[0], 1, s);
dfs(1, 0);
lca::init();
int lastans=0;
while(m--){
int u=read()^lastans,v=read(),k=read();
int tmp=lca::lca(u, v);
lastans=val_sort[query(rot[u], rot[v], rot[tmp], rot[f[tmp][0]], 1, s, k)];
printf("%d\n", lastans);
}
return 0;
}

Count on a tree 树上主席树的更多相关文章

  1. 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 ...

  2. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  3. 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  4. 【洛谷 P2633】 Count on a tree(主席树,树上差分)

    题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...

  5. BZOJ2588 SPOJ10628 Count on a tree 【主席树】

    BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...

  6. bzoj 2588 Spoj 10628. Count on a tree(主席树)

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

  7. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  8. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  9. 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树

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

随机推荐

  1. VS.NET(C#)--2.8HTML服务器控件

    HTML服务器控件 服务器不处理HTML控件,例如:<h1>.<a>超链接.<input>,直接送到客户端,由浏览器呈现. 把HTML控件转换成HTML服务器控件, ...

  2. springboot下@webfilter的使用

    启动类加了@ServletComponentScan,无论过滤器类加不加@Componment urlPatterns = {"/test/*"}都可以生效 单使用@Compone ...

  3. js 单线程 异步

    线程与进程: 进程是系统资源分配和调度的单元.一个运行着的程序就对应一个进程.在windows中,每一个打开的运行的应用程序或后台程序,比如运行中的qq,谷歌浏览器,网易云音乐,资源管理器等都是一个进 ...

  4. wampserver的使用配置

    1.正常安装就不说了,只需要把安装位置改成需要的位置就可以了.其它的默认就可以了. 2.安装完成之后打开wampserver. 3.现在该修改密码了: (1)点击进入mysql控制台. (2)Wamp ...

  5. pygame安装遇到的坑

    坑一:python版本冲突,电脑同时安装多个版本的python,由于每个都是python.exe,cmd命令窗口输入的python不一定是你想要的版本,所以最好还是安装单个版本即可. 坑二:由于电脑安 ...

  6. IO模型之AIO代码及其实践详解

    一.AIO简介 AIO是java中IO模型的一种,作为NIO的改进和增强随JDK1.7版本更新被集成在JDK的nio包中,因此AIO也被称作是NIO2.0.区别于传统的BIO(Blocking IO, ...

  7. MySQL5.7安装、主从复制、读写分离原理解析以及详细配置

    一.Linux下mysql彻底卸载 1.查看mysql的安装情况 rpm -qa | grep -i mysql 2.删除上图安装的软件 rpm -ev mysql-community-libs--. ...

  8. 【SpringMVC】请求乱码处理

    一.post请求乱码 二.get请求乱码 一.post请求乱码 在web.xml中加入 <filter> <filter-name>CharacterEncodingFilte ...

  9. vi编辑器简介

    vi编辑器是Linux和Unix上最基本的文本编辑器,工作在字符模式下.由于不需要图形界面,vi是效率很高的文本编辑器.尽管在Linux上也有很多图形界面的编辑器可用,但vi在系统和服务器管理中的功能 ...

  10. _MyBatis3-topic06.07.08.09_ 全局配置文件_引入dtd约束(xml提示)/ 引入properties引用/ 配置驼峰命名自动匹配 /typeAliases起别名.批量起别名

    MyBatis3 的全局配置文件 : Setting -官方文档 笔记要点 出错分析 [Intellij idea配置外部DTD文件] 设置步骤: (同Eclipse中的Catalog设置 ) Fil ...