Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。最后一个询问不输出换行符

Sample Input

8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

HINT

N,M<=100000
暴力自重。。。
 
 
在树上建主席树,统计答案时为避免LCA被减两次,计算sum[x]+sum[y]-sum[lca(x,y)]-sum[fa[lca(x,y)]]。
 #include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=1e5+;
int n,m,tot,x,y,rk,cnte,ind,cnt,temp,lastans;
int v[N],tmp[N],first[N],id[N],num[N],root[N];
int deep[N],fa[N][];
struct node{int lc,rc,sum;}tr[N*];
struct edge{int to,next;}e[N*];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void ins(int u,int v){e[++cnte]=(edge){v,first[u]};first[u]=cnte;}
void insert(int u,int v){ins(u,v);ins(v,u);}
void dfs(int x)
{
ind++;id[x]=ind;num[ind]=x;
for(int i=;(<<i)<=deep[x];i++)fa[x][i]=fa[fa[x][i-]][i-];
for(int i=first[x];i;i=e[i].next)
{
if(deep[e[i].to])continue;
fa[e[i].to][]=x;deep[e[i].to]=deep[x]+;dfs(e[i].to);
}
}
int lca(int ri,int rj)
{
if(deep[ri]<deep[rj])swap(ri,rj);
int d=deep[ri]-deep[rj];
for(int i=;(<<i)<=d;i++)if((<<i)&d)ri=fa[ri][i];
if(ri==rj)return ri;
for(int i=;i>=;i--)
if((<<i)<=deep[ri]&&fa[ri][i]!=fa[rj][i])
ri=fa[ri][i],rj=fa[rj][i];
return fa[ri][];
}
void update(int &x,int last,int L,int R,int num)
{
x=++cnt;tr[x].sum=tr[last].sum+;
if(L==R)return;
tr[x].lc=tr[last].lc;tr[x].rc=tr[last].rc;
int mid=(L+R)>>;
if(num<=mid)update(tr[x].lc,tr[last].lc,L,mid,num);
else update(tr[x].rc,tr[last].rc,mid+,R,num);
}
int query(int x,int y,int rk)
{
int a=x,b=y,c=lca(x,y),d=fa[c][];
a=root[id[x]];b=root[id[b]];c=root[id[c]];d=root[id[d]];
int L=,R=tot;
while(L<R)
{
int mid=(L+R)>>;
temp=tr[tr[a].lc].sum+tr[tr[b].lc].sum-tr[tr[c].lc].sum-tr[tr[d].lc].sum;
if(temp>=rk)R=mid,a=tr[a].lc,b=tr[b].lc,c=tr[c].lc,d=tr[d].lc;
else rk-=temp,L=mid+,a=tr[a].rc,b=tr[b].rc,c=tr[c].rc,d=tr[d].rc;
}
return tmp[L];
}
int main()
{
n=read();m=read();
for(int i=;i<=n;i++)v[i]=tmp[i]=read();
sort(tmp+,tmp+n+);tot=unique(tmp+,tmp+n+)-tmp-;
for(int i=;i<=n;i++)v[i]=lower_bound(tmp+,tmp+tot+,v[i])-tmp;
for(int i=;i<n;i++)x=read(),y=read(),insert(x,y);
deep[]=;dfs();
for(int i=;i<=n;i++)
{
temp=num[i];
update(root[i],root[id[fa[temp][]]],,tot,v[temp]);
}
for(int i=;i<=m;i++)
{
x=read();y=read();rk=read();x^=lastans;
lastans=query(x,y,rk);printf("%d",lastans);
if(i!=m)printf("\n");
}
return ;
}

【bzoj 2588】Spoj 10628. Count on a tree的更多相关文章

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

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

  2. 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  3. 【BZOJ】【2588】COT(Count On a Tree)

    可持久化线段树 maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树. 然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 19 ...

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

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

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

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

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

  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 (可持久化线段树)

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

随机推荐

  1. Distinct Values(2018hdu多校第一场)

    给你一段长度为n的区间,然后在给你m个小区间,要求这m个小区间里的每个人都不能重复,请你输出字典序最小的方案. 我们可以开一个suf数组,表示我到我后面的不出现重复数字的区间至少需要到达的位置.所以对 ...

  2. BZOJ4669抢夺(费用流+二分答案)

    题目描述 大战将至, 美国决定实行计划经济.美国西部总共有 N 个城市,编号 为 0 ∼ N − 1,以及 M 条道路,道路是单向的.其中城市 0 是一个大城 市,里面住着 K 个人,而城市 N − ...

  3. 微信小程序支付(PHP后端)

    1.申请开通小程序支付,我们正式开通的微信支付是在微信公众平台上,我们需要绑定之前的微信商户平台即可,这一点不过多强调 2.小程序支付开发步骤 (1).统一下单 大家看到微信的统一下单接口密密麻麻的一 ...

  4. python学习day7 深浅拷贝&文件操作

    4-4 day07 深浅拷贝&文件操作 .get()用法 返回指定键的值,如果值不在字典中返回默认值. info={'k1':'v1,'K2':'v2'}mes = info.get('k1' ...

  5. pre标签内文本自动换行

    pre标签内文本自动换行 给pre标签添加一个css样式 pre { white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap; /* ...

  6. Java 并发集合的实现原理

    http://www.codeceo.com/article/the-implementation-principle-of-java-concurrent-collection.html 阿凡卢   ...

  7. js 读取包含特殊字符的属性值

    在JS中对象的属性可以通过两种方式访问:object.property和object["property"]. 包含特殊字符的属性只能以此方式访问: object["pr ...

  8. ArcGIS for qml - 地址地标转换为经纬度(地理编码)

    实现输入地址地标转换为其经纬度 本文链接:地理编码 作者: 狐狸家的鱼 Github: 八至 一.地理编码 1.地理编码含义 地址编码(或地理编码)是使用地址中包含的信息来插入地图上的相应位置的过程. ...

  9. Linux中编译或安装程序时提示No such file or directory

    deb系发行版本 Debian Ubuntu Linux Mint等 dpkg -S dpkg-query -S rpm系发行版本 RHEL CentOS等 yum provides rpm -qf ...

  10. A1143. Lowest Common Ancestor

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...