主席树初探--BZOJ2588: Spoj 10628. Count on a tree
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的更多相关文章
- 【主席树】bzoj2588 Spoj 10628. Count on a tree
每个点的主席树的root是从其父转移来的.询问的时候用U+V-LCA-FA(LCA)即可. #include<cstdio> #include<algorithm> using ...
- BZOJ2588: Spoj 10628. Count on a tree
传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...
- 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 ...
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA
[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...
- 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 树上跑主席树
2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...
- 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 ...
- 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个节点的树,每个点 ...
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...
随机推荐
- SecureCRT 迁移到新环境,导出配置文件目录 转
SecureCRT 打开SecureCRT,点击菜单栏的“选项”--“全局选项” 在打开的窗口中,选择“常规”,在右侧找到“配置文件夹”,这个就是SecureCRT的配置文件目录. 复制这个路径并且进 ...
- TestNG基本注解(二)
1. Before类别和After类别注解 @BeforeSuite @AfterSuite @BeforeTest @AfterTest @BeforeClass @AfterClass @Befo ...
- RabbitMQ七:交换机类型Exchange Types--Fanout 介绍
前言 最新版本的RabbitMQ有四种交换机类型,分别是Direct exchange.Fanout exchange.Topic exchange.Headers exchange. 其中之前我们用 ...
- mvc的生命周期
尽管每次都是从msdn里复制粘贴,但是还是有必要的,加深对mvc的理解和官方的表述. 了解 MVC 应用程序执行过程 发送给基于 ASP.NET MVC 的 Web 应用程序的请求首先通过 UrlRo ...
- iOS Programming Camera 2
iOS Programming Camera 2 1.1 Creating BNRImageStore The image store will fetch and cache the image ...
- Linux下Eclipse连接小米手机真机调试
以前用Ubuntu 12.04可以真机调试,连上手机就可以了,上次看pear os 好看于是下了个玩玩(界面风格像mac 买不起,仿得起),这次想开发安卓发现真机调试不了了...于是乎各种找资料,各种 ...
- this常用的用法
1.函数作为对象的方法时,this指的是该对象: var obj ={ name:"bob", age:25, getName:function(){ console.log(th ...
- WebSocket 的一些简单页面推送使用
因为做通信项目的时候,需要实时获取每个分机的当前状态,发现websocket还不错,只是对浏览器的要求比较高, 针对特定用户推送消息,网上有一些 public class GetHttpSession ...
- 用Python控制摄像头拍照并发邮件
概述前言 工具 思路 安装及导入包 设置参数 实现拍照 构造邮件内容 发送邮件 判断网络连接 开机自启 后记 o1 前言为什么会有写这个程序的想法呢? 最初的想法是写一个可以用电脑前置摄像头拍照的程序 ...
- linux下查找字符串的命令
1. set命令可以显示出当前shell下所有全局参量定义及其值; 2. 查找并删除当前目录下小文件: find . -type f -size -10k -exec rm {} \; 说明: w ...