Count on a tree 树上主席树
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 树上主席树的更多相关文章
- 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 ... 
- 【BZOJ2588】Count On a Tree(主席树)
		[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ... 
- 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)
		洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ... 
- 【洛谷 P2633】 Count on a tree(主席树,树上差分)
		题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ... 
- BZOJ2588 SPOJ10628 Count on a tree 【主席树】
		BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ... 
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
		Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ... 
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
		Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ... 
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
		洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ... 
- 【bzoj2588】Spoj 10628. Count on a tree  离散化+主席树
		题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ... 
随机推荐
- Arm-Linux 移植 ssh
			背景: 自己拥有一块开发板,但是苦于上面没有ssh,比较不方便.正好趁这个机会,移植ssh.我们使用的ssh是openssh. host平台 :Ubuntu 18.04 arm平台 : S5P6818 ... 
- Z算法板子
			给定一个串$s$, $Z$算法可以$O(n)$时间求出一个$z$数组 $z_i$表示$s[i...n]$与$s$的前缀匹配的最长长度, 下标从$0$开始 void init(char *s, int ... 
- vs setup 自动下载依赖的framework配置
			1.项目->属性->签名->选中为ClickOnce清单签名->创建测试证书 2.项目->属性->安全性->启用ClickOnce安全设置 3.setup项目 ... 
- 关于Vue中,$this.router.push到当前页面,只是传入参数不同,页面不刷新的问题解决
			在页面的watch中,监听$router的变化 watch: { $route (to, from) { this.$router.go(0) } } 其中this.$router.go(0)为刷新页 ... 
- 动画 jquery-transit
			<script type="text/javascript" src="js/jquery.min.js"></script> < ... 
- Fatal error:Call to undefined function mysqli_connect() in .php line 报错
			这样的问题,多半是PHP配置问题. 修改php配置文件 1.在php(版本:php-7.2.7-Win32-VC15-x64)文件夹中一开始不会看到php.ini,而是php.ini-developm ... 
- Mycat学习-单独启动mycat
			Mycat下载地址:http://mycat.io/ Mycat安装:解压缩即可. Mycat作为一个中间件,实现mysql协议,是可以不依赖数据库单独运行的. 对前端应用连接来说就是一个数据库, ... 
- FAILED: SemanticException Unable to determine if hdfs://tmaster:8020/user/root/words.db/test_t2 is encrypted
			使用hive时,建立数据库,建表,写数据: 读数据:select * from test_t2; 报错SemanticException 原因:建表时使用了其他路径,或者在另一个路径的数据库(建立数 ... 
- MySQL 数据库的高可用性分析
			MySQL数据库是目前开源应用最大的关系型数据库,有海量的应用将数据存储在MySQL数据库中.存储数据的安全性和可靠性是生产数据库的关注重点.本文分析了目前采用较多的保障MySQL可用性方案. MyS ... 
- 个性化召回算法实践(四)——ContentBased算法
			ContentBased算法的思想非常简单:根据用户过去喜欢的物品(本文统称为 item),为用户推荐和他过去喜欢的物品相似的物品.而关键就在于这里的物品相似性的度量,这才是算法运用过程中的核心. C ... 
