题目链接

/*
序列上的主席树 某点是利用前一个点的根建树
同理 树上的主席树 某个节点可以利用其父节点(is unique)的根建树
排名可以利用树上前缀和求得: 对于(u,v),w=LCA(u,v),u->v这条链的值就是 sum[u->root]+sum[v->root]-sum[w->root]-sum[fa[w]->root](减一个w)
这样like序列上的主席树 用两棵树进行差分,树上的用四棵树即可
每个节点是一棵权值线段树 和给的树是独立的 没什么关系 别想错
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
//#define gc() getchar()
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=1e5+5,MAXIN=2e5; int n,m,cnt,W[N],A[N],ref[N],fa[N],Enum,H[N],to[N<<1],nxt[N<<1],root[N];
char IN[MAXIN],*SS=IN,*TT=IN;
namespace Subdivision//for LCA
{
int dep[N],sz[N],son[N],top[N];
void DFS1(int x)
{
sz[x]=1; int mx=0;
for(int v,i=H[x]; i; i=nxt[i])
if((v=to[i])!=fa[x])
{
dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
if(mx<sz[v]) mx=sz[v],son[x]=v;
}
}
void DFS2(int x,int tp)
{
top[x]=tp;
if(son[x])
{
DFS2(son[x],tp);
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa[x] && to[i]!=son[x])
DFS2(to[i],to[i]);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v] ? v : u;
}
}
struct Seg_Tree
{
int tot,sum[N*18],son[N*18][2];
void Insert(int x,int &y,int l,int r,int p/*,int v*/)
{
sum[y=++tot]=sum[x]+1;
if(l<r)
{
int m=l+r>>1;
if(p<=m) son[y][1]=son[x][1],Insert(son[x][0],son[y][0],l,m,p);
else son[y][0]=son[x][0],Insert(son[x][1],son[y][1],m+1,r,p);
}
}
int Query(int faLca,int Lca,int x,int y,int l,int r,int k)
{
if(l==r) return l;
int m=l+r>>1, tmp=sum[son[x][0]]+sum[son[y][0]]-sum[son[Lca][0]]-sum[son[faLca][0]];
if(tmp>=k) return Query(son[faLca][0],son[Lca][0],son[x][0],son[y][0],l,m,k);
else return Query(son[faLca][1],son[Lca][1],son[x][1],son[y][1],m+1,r,k-tmp);
}
}t;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AddEdge(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS(int x,int f)
{
t.Insert(root[f],root[x],1,cnt,A[x]/*,1*/);
fa[x]=f;
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa[x]) DFS(to[i],x);
}
inline int Find(int x)
{
int l=1,r=cnt,m;
while(l<r)
{
if(ref[m=l+r>>1]<x) l=m+1;
else r=m;
}
return l;
}
void Discrete()
{
std::sort(ref+1,ref+1+n);
cnt=1;
for(int i=2; i<=n; ++i)
if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int p,i=1; i<=n; ++i)
W[p=Find(A[i])]=A[i], A[i]=p;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("2588.in","r",stdin);
#endif n=read(),m=read()-1;
for(int i=1; i<=n; ++i) ref[i]=A[i]=read();
for(int u,v,i=1; i<n; ++i) u=read(),v=read(),AddEdge(u,v);
Discrete(), DFS(1,0);
Subdivision::DFS1(1), Subdivision::DFS2(1,1);
int ans=0,u,v,k,w;
while(m--)
{
u=ans^(read()),v=read(),k=read(),w=Subdivision::LCA(u,v);
printf("%d\n",ans=W[t.Query(root[fa[w]],root[w],root[u],root[v],1,cnt,k)]);
}
u=ans^(read()),v=read(),k=read(),w=Subdivision::LCA(u,v);
printf("%d",W[t.Query(root[fa[w]],root[w],root[u],root[v],1,cnt,k)]); return 0;
}

第二次写(2018.4.4):

//10^5还是需要18*10^5的空间!
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1e5+5; int n,Q,cnt,ref[N],A[N],H[N],Enum,nxt[N<<1],to[N<<1],root[N],top[N],dep[N],sz[N],son[N],fa[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AddEdge(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
namespace T//Seg_Tree
{
#define lson son[x][0]
#define rson son[x][1] int tot,sum[N*17],son[N*17][2];
void Insert(int x,int &y,int l,int r,int p)
{
sum[y=++tot]=sum[x]+1;
if(l<r){
int m=l+r>>1;
if(p<=m) son[y][1]=rson,Insert(lson,son[y][0],l,m,p);
else son[y][0]=lson,Insert(rson,son[y][1],m+1,r,p);
}
}
int Query(int x,int y,int lca,int falca,int l,int r,int k)
{
if(l==r) return l;
int delta=sum[lson]+sum[son[y][0]]-sum[son[lca][0]]-sum[son[falca][0]];
if(delta<k) return Query(rson,son[y][1],son[lca][1],son[falca][1],(l+r>>1)+1,r,k-delta);
return Query(lson,son[y][0],son[lca][0],son[falca][0],l,l+r>>1,k);
}
} int Find(int x)
{
int l=1,r=cnt,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
void DFS1(int x)
{
int mx=0; sz[x]=1;
T::Insert(root[fa[x]],root[x],1,cnt,A[x]);
for(int v,i=H[x]; i; i=nxt[i])
if((v=to[i])!=fa[x])
{
fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v],son[x]=v;
}
}
void DFS2(int x,int tp)
{
top[x]=tp;
if(son[x]){
DFS2(son[x],tp);
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa[x] && to[i]!=son[x]) DFS2(to[i],to[i]);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v]?v:u;
} int main()
{
n=read(),Q=read();
for(int i=1; i<=n; ++i) ref[i]=A[i]=read();
for(int u,v,i=1; i<n; ++i) u=read(),v=read(),AddEdge(u,v);
std::sort(ref+1,ref+1+n), cnt=1;
for(int i=2; i<=n; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=n; ++i) A[i]=Find(A[i]);
DFS1(1), DFS2(1,1);
int res=0,u,v,w,k;
while(Q--)
u=read()^res,v=read(),k=read(),w=LCA(u,v),
printf("%d\n",res=ref[T::Query(root[u],root[v],root[w],root[fa[w]],1,cnt,k)]); return 0;
}

BZOJ.2588.Count on a tree(主席树 静态树上第k小)的更多相关文章

  1. spoj COT - Count on a tree(主席树 +lca,树上第K大)

    您将获得一个包含N个节点的树.树节点的编号从1到Ñ.每个节点都有一个整数权重. 我们会要求您执行以下操作: uvk:询问从节点u到节点v的路径上的第k个最小权重 输入 在第一行中有两个整数Ñ和中号.( ...

  2. SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  3. SPOJ 10628 Count on a tree(Tarjan离线 | RMQ-ST在线求LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  4. 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)

    题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  5. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

  6. HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

    HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...

  7. 主席树--动态区间第k小

    主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...

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

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

  9. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

随机推荐

  1. python 历险记(四)— python 中常用的 json 操作

    目录 引言 基础知识 什么是 JSON? JSON 的语法 JSON 对象有哪些特点? JSON 数组有哪些特点? 什么是编码和解码? 常用的 json 操作有哪些? json 操作需要什么库? 如何 ...

  2. git 的入门使用到团队协作

    1.git 的安装.下载---安装,esay. 下载地址:https://git-for-windows.github.io/ 2.创建一个自己的身份 git config --global user ...

  3. dellR720服务器设置光盘引导流程安装cenos7

    1.开机,按F10,进入系统引导界面,选择加载系统选项,并选择redhat 7.1选项 系统提示不支持,选择仍然继续,根据提示设置BIOS设置启动,重启 2.根据提示按F11进入BIOS启动设置,选择 ...

  4. ANN算法总结

    kd-tree kd-tree works poorly in high dimensions (k<30) 自己实验的时候差不多20到30左右吧,超过之后,就真的很慢了 faiss suppo ...

  5. JS算法之二分查找

    二分查找法主要是解决「在一堆有序的数中找出指定的数」这类问题,不管这些数是一维数组还是 多维数组,只要有序,就可以用二分查找来优化. 二分查找是一种「分治」思想的算法,大概流程如下: 1.数组中排在中 ...

  6. OCM_第三天课程:Section1 —》表空间的操作和管理、服务配置

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  7. jquery----用户密码验证

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Math 对象

    Math对象提供了,我们一般进行数学运算的所有函数. Math.random() 随机0~1之间的随机数 [0, 1) Math.max() 求传入参数的最大数 Math.min() 求传入参数的最小 ...

  9. Java 使用Jedis连接Redis数据库(-)

    redis 安装: Linux 安装redis 1)下载jar包: 使用Jedis需要以下两个jar包: jedis-2.8.0.jar commons-pool2-2.4.2.jar 2)测试red ...

  10. 配置CenOS网络,并用Xshell链接。

    首先输入 cd /etc/sysconf ig/network-scripts/ 然后回车 输入ls 然后回车 输入 vi ifcfg-eth0  然后回车 按下esc键,然先后按下U,I键把光标用键 ...