题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=2588

题解:

主席树,在线,(求LCA)
感觉主席树真的好厉害。。。
在原树上建主席树。
即对于原树的节点 u ,它所对应的线段树维护的是原树中它到根的路径上的点的权值信息。
即建主席树时, u 的线段树是由 fa[u] 的线段树而来的。
然后对于询问的两个点 a,b,
得到其 LCA,记为 c,并令 d = fa[c]
那么 a 到 b 路径上的信息即为
a 对应的线段树 + b 对应的线段树 - c 对应的线段树 - d 对应的线段树
所以在主席树中直接查询第 K 小就好了。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100500
#define filein(x) freopen(#x".in","r",stdin)
#define fileout(x) freopen(#x".out","w",stdout)
using namespace std;
int A[MAXN],tmp[MAXN],bgs[MAXN],top[MAXN],dep[MAXN],fa[MAXN];
int N,M,tnt;
struct Edge{
int to[MAXN*2],nxt[MAXN*2],head[MAXN],ent;
void Reset(){
ent=2;
memset(head,0,sizeof(head));
}
void Adde(int u,int v){
to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
to[ent]=u; nxt[ent]=head[v]; head[v]=ent++;
}
}E;
struct CMT{
int rt[MAXN],ls[MAXN*20],rs[MAXN*20],cnt[MAXN*20],sz;
void Insert(int &u,int l,int r,int p){
sz++; ls[sz]=ls[u]; rs[sz]=rs[u]; cnt[sz]=cnt[u];
u=sz; cnt[u]++; if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) Insert(ls[u],l,mid,p);
else Insert(rs[u],mid+1,r,p);
}
int Query(int a,int b,int c,int d,int l,int r,int K){
if(l==r) return l;
int mid=(l+r)>>1,lcnt=cnt[ls[a]]+cnt[ls[b]]-cnt[ls[c]]-cnt[ls[d]];
if(K<=lcnt) return Query(ls[a],ls[b],ls[c],ls[d],l,mid,K);
else return Query(rs[a],rs[b],rs[c],rs[d],mid+1,r,K-lcnt);
}
}DT;
void read(int &x){
static int f; static char ch;
x=0; f=1; ch=getchar();
while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=x*f;
}
void dfs1(int u,int dad){
static int num[MAXN];
DT.rt[u]=DT.rt[dad];
DT.Insert(DT.rt[u],1,tnt,A[u]);
num[u]=1; fa[u]=dad; int bgn=0;
for(int i=E.head[u],v;i;i=E.nxt[i]){
v=E.to[i]; if(v==dad) continue;
dfs1(v,u); num[u]+=num[v];
if(num[v]<=bgn) continue;
bgs[u]=v; bgn=num[v];
}
}
void dfs2(int u,int tp){
top[u]=tp; dep[u]=dep[fa[u]]+1;
if(bgs[u]) dfs2(bgs[u],tp);
for(int i=E.head[u],v;i;i=E.nxt[i]){
v=E.to[i]; if(v==fa[u]||v==bgs[u]) continue;
dfs2(v,v);
}
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]) swap(u,v);
v=fa[top[v]];
}
if(dep[u]>dep[v]) swap(u,v);
return u;
}
void solve(){
int lastANS=0,a,b,c,d,rta,rtb,rtc,rtd,K,p;
for(int i=1;i<=M;i++){
read(a); read(b); read(K);
a^=lastANS; c=lca(a,b); d=fa[c];
rta=DT.rt[a]; rtb=DT.rt[b];
rtc=DT.rt[c]; rtd=DT.rt[d];
p=DT.Query(rta,rtb,rtc,rtd,1,tnt,K);
lastANS=tmp[p];
printf("%d",lastANS);
if(i!=M) printf("\n");
}
}
int main(){
E.Reset();
read(N); read(M);
for(int i=1;i<=N;i++)
read(A[i]),tmp[i]=A[i];
sort(tmp+1,tmp+N+1);
tnt=unique(tmp+1,tmp+N+1)-tmp-1;
for(int i=1;i<=N;i++)
A[i]=lower_bound(tmp+1,tmp+tnt+1,A[i])-tmp;
for(int i=1,u,v;i<N;i++)
scanf("%d%d",&u,&v),E.Adde(u,v);
dfs1(1,0);
dfs2(1,1);
solve();
return 0;
}

●BZOJ 2588 Spoj 10628. 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. 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 ...

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

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

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

  5. 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个节点的树,每个点 ...

  6. bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)

    Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 7669  Solved: 1894[Submi ...

  7. 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree

    题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...

  8. BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

    分析:树上第k小,然后我想说的是主席树并不局限于线性表 详细分析请看http://www.cnblogs.com/rausen/p/4006116.html,讲的很好, 然后因为这个熟悉了主席树,真是 ...

  9. 洛谷 2633 BZOJ 2588 Spoj 10628. Count on a tree

    [题解] 蜜汁强制在线... 每个点开一个从它到根的可持久化权值线段树.查询的时候利用差分的思想在树上左右横跳就好了. #include<cstdio> #include<algor ...

随机推荐

  1. Linux下进程间通信--共享内存:最快的进程间通信方式

    共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...

  2. jQuery函数学习

    函数:after(content) 功能:在每个匹配的元素后面添加html内容 返回:jQuery对象 参数:content (<Content>): Content to insert ...

  3. DML数据操作语言之常用函数

    所谓函数,就是输入某一值,得到相应的输出结果的功能.相当于一个加工厂,给了原料,最终产出成品. 其中原料 就是参数(parameter). 产品 就是返回值. 函数大致可以分为以下五个种类: 算术函数 ...

  4. TensorFlow-谷歌深度学习库 手把手教你如何使用谷歌深度学习云平台

    自己的电脑跑cnn, rnn太慢? 还在为自己电脑没有好的gpu而苦恼? 程序一跑一俩天连睡觉也要开着电脑训练? 如果你有这些烦恼何不考虑考虑使用谷歌的云平台呢?注册之后即送300美元噢-下面我就来介 ...

  5. python性能分析--cProfile

    Python标准库中提供了三种用来分析程序性能的模块,分别是cProfile, profile和hotshot,另外还有一个辅助模块stats.这些模块提供了对Python程序的确定性分析功能,同时也 ...

  6. 使用 HttpClient 请求 Web Api

    1.获取 post 请求 body 内容 [HttpPost] public string GetId() { //如果方法参数里面有 [FromBody],则需要重新调整内容指针,再进行读取. // ...

  7. 算法题丨3Sum

    描述 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all ...

  8. Spring Framework 的 Assert断言

    知识共享才能传播,博采众家之长,才能推陈出新!-- 参考 https://www.cnblogs.com/hwaggLee/p/4778101.html 一.什么是 Assert(断言)? Web 应 ...

  9. HTTP协议扫盲(六)InputStream的复用

    一.问题提出 在进行网关引擎开发时,获取到一个http请求的inputstream后,可能要多次利用它进行read操作.由于流读过一次就不能再读了,所以需要实现InputStream的复制. 而Inp ...

  10. vi和vim编辑器

    VI vi是一种计算机文本编辑器,由美国计算机科学家比尔·乔伊(Bill Joy)完成编写,并于1976年以BSD协议授权发布. VIM Vim是从vi发展出来的一个文本编辑器.其代码补完.编译及错误 ...