n<=100000的点权树,有m<=100000个询问,每次问两个点间的第k小点权,保证有解,强制在线。

主席上树啦!类似于之前的序列不带修改询问的前缀表示法,现在只要把前缀当成某点到根的信息即可。然后比如要问x点和y点,z为lca(x,y),w为z的爸爸,那么x,y,z,w四棵线段树一起跑即可。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
//#include<iostream>
using namespace std; int n,m;
#define maxn 100011
#define maxm 2000011
struct SMT
{
struct Node
{
int son[];
int cnt;
}a[maxm];
int size,n;
void clear(int m) {n=m;size=;a[].cnt=;}
void build(int pre,int &rt,int L,int R,int num)
{
rt=++size;
a[rt].cnt=a[pre].cnt+;
if (L==R) {a[rt].son[]=a[rt].son[]=;return;}
const int mid=(L+R)>>;
if (num<=mid) build(a[pre].son[],a[rt].son[],L,mid,num),a[rt].son[]=a[pre].son[];
else build(a[pre].son[],a[rt].son[],mid+,R,num),a[rt].son[]=a[pre].son[];
}
void build(int pre,int &rt,int num) {build(pre,rt,,n,num);}
// void test(int x,int L,int R)
// {
// const int mid=(L+R)>>1;
// if (a[x].son[0]) test(a[x].son[0],L,mid);
//// cout<<L<<' '<<R<<' '<<a[x].cnt<<endl;
// if (a[x].son[1]) test(a[x].son[1],mid+1,R);
// }
// void test(int x) {test(x,1,n);}
}smt; struct Edge{int to,next;}edge[maxn<<];int first[maxn],le=;
void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
void insert(int x,int y) {in(x,y);in(y,x);} int a[maxn],b[maxn],lb;
int fa[maxn][],dep[maxn],rt[maxn];
void dfs(int x,int f)
{
fa[x][]=f;dep[x]=dep[f]+;
for (int j=;j<=;j++)
fa[x][j]=fa[fa[x][j-]][j-];
smt.build(rt[f],rt[x],a[x]);
for (int i=first[x];i;i=edge[i].next)
{
const Edge &e=edge[i];if (e.to==f) continue;
dfs(e.to,x);
}
}
void pre() {dfs(,);} int lca(int x,int y)
{
if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
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][];
} int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
lb=n;sort(b+,b++lb);lb=unique(b+,b++lb)-b-;
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b++lb,a[i])-b; smt.clear(lb);
for (int i=,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
insert(x,y);
}
pre();
// for (int i=1;i<=n;i++) smt.test(rt[i]),cout<<endl;
int last=;
for (int i=,x,y,K;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&K);
x^=last;
int z=lca(x,y),w=fa[z][],L=,R=lb,tmp;
// cout<<x<<' '<<y<<' '<<z<<' '<<w<<endl;
x=rt[x];y=rt[y];z=rt[z];w=rt[w];
while (L<R)
{
if ((tmp=smt.a[smt.a[x].son[]].cnt+smt.a[smt.a[y].son[]].cnt
-smt.a[smt.a[z].son[]].cnt-smt.a[smt.a[w].son[]].cnt)>=K)
x=smt.a[x].son[],y=smt.a[y].son[],z=smt.a[z].son[],w=smt.a[w].son[],R=(L+R)>>;
else x=smt.a[x].son[],y=smt.a[y].son[],z=smt.a[z].son[],w=smt.a[w].son[],K-=tmp,L=((L+R)>>)+;
// cout<<tmp<<' '<<K<<endl;
}
printf("%d",(last=b[L]));
if (i<m) puts("");
}
return ;
}

主席树初探--BZOJ2588: Spoj 10628. Count on a tree的更多相关文章

  1. 【主席树】bzoj2588 Spoj 10628. Count on a tree

    每个点的主席树的root是从其父转移来的.询问的时候用U+V-LCA-FA(LCA)即可. #include<cstdio> #include<algorithm> using ...

  2. BZOJ2588: Spoj 10628. Count on a tree

    传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...

  3. bzoj2588: Spoj 10628. Count on a tree(树上第k大)(主席树)

    每个节点继承父节点的树,则答案为query(root[x]+root[y]-root[lca(x,y)]-root[fa[lca(x,y)]]) #include<iostream> #i ...

  4. 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

    [BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...

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

  6. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  7. Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...

  8. Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...

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

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

随机推荐

  1. yum 安装报错:*epel: mirrors.aliyun.comError: xzcompressionnot available

    环境背景:epel源下载地址: http://mirrors.aliyun.com/Centos内核内核版本[root@nfs01 ~]# uname -r2.6.32-642.el6.x86_64= ...

  2. 使用ImageMagick处理图片后导致图片变大的问题

    最新在使用ImageMagick处理图片时,发现有时经过处理的图片变大的问题. 例如原图为27K,经处理后的图片会变为77K. 先看测试代码: // imgtest.cpp : 定义控制台应用程序的入 ...

  3. Spring注解驱动开发之AOP

    前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...

  4. 三种将list转换为map的方法(传统方法、jdk8 Stream流、guava)

    三种将list转换为map的方法 - jackyrong - ITeye博客:http://jackyrong.iteye.com/blog/2158009

  5. RegisterClientScriptBlock和RegisterStartupScript的区别

    RegisterClientScriptBlock在 Page 对象的 元素的开始标记后立即发出客户端脚本,RegisterStartupScript则是在Page 对象的 元素的结束标记之前发出该脚 ...

  6. 提高SQL查询效率 的10大方法

    一.查询条件精确,针对有参数传入情况 二.SQL逻辑执行顺序 FROM–>JOIN–>WHERE–>GROUP–>HAVING–>DISTINCT–>ORDER–& ...

  7. MVC学习(一)

    http://www.cnblogs.com/QLeelulu/archive/2008/09/30/1302462.html

  8. Linux下PPPoE Server测试环境搭建

    1.1  服务器软件安装 安裝PPPoE Server 所需的软件: 安装ppp模块: sudo apt-get install ppp   //一般默认下已安装 安装rp-pppoe,从网络上下载安 ...

  9. matlab中数据类型

    在MATLAB中有15种基本数据类型,分别是8种整型数据.单精度浮点型.双精度浮点型.逻辑型.字符串型.单元数组.结构体类型和函数句柄.这15种基本数据类型具体如下. 有符号整数型:int8,int1 ...

  10. swift不同地方 命名空间module iOS

    Objective-C没有命名空间,为了避免冲突,Objective-C的类型一般都会加上两到三个字母的前缀,比如Apple保留的NS和UI前缀,各个系统框架的前缀,各个系统框架的前缀SK(Store ...