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


Sample Output


HINT

N,M<=100000
暴力自重。。。

Source

鸣谢seter

Solution

普通的树上主席树

先上我的TLE树链剖分+主席树

#include<map>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100010
#define buf 1<<21
using namespace std;
char B[buf],*p=B;
inline int Rin(){
int x=,f=;
for(;*p<''||*p>'';p++)
if(*p=='-')f=-;
for(;*p>=''&&*p<='';p++)
x=(x<<)+(x<<)+*p-'';
return x*f;
}
bool vis[N];
vector<int>d;
map<int,int>h;
int ind,n,q,ans,val[N],sz[N],rk[N],id[N],mx[N],fa[N],dep[N],top[N];
struct pt{
int v;pt *nt;
}*fst[N],mem[N<<],*e=mem;
inline void link(int x,int y){
*++e=(pt){y,fst[x]},fst[x]=e;
*++e=(pt){x,fst[y]},fst[y]=e;
}
void dfs1(int x){
rk[++ind]=x,
id[x]=ind,
vis[x]=sz[x]=;
for(pt *j=fst[x];j;j=j->nt)
if(!vis[j->v])
fa[j->v]=x,
dep[j->v]=dep[x]+,
dfs1(j->v),sz[x]+=sz[j->v],
mx[x]=sz[mx[x]]<sz[j->v]?j->v:mx[x];
}
void dfs2(int x){
vis[x]=;
top[x]=x^mx[fa[x]]?x:top[fa[x]];
if(mx[x]){
dfs2(mx[x]);
for(pt *j=fst[x];j;j=j->nt)
if(vis[j->v])dfs2(j->v);
}
}
inline int lca(int x,int y){
while(top[x]^top[y])
dep[top[x]]>dep[top[y]]?
x=fa[top[x]]:
y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
struct Seg{
Seg *l,*r;int s;
Seg(){}
Seg(Seg *_l,Seg *_r,int _s)
:l(_l),r(_r),s(_s){}
}*rt[N],*nil=new Seg(0x0,0x0,);
Seg *build(Seg *p,int s,int t,int k){
if(!(s^t))return new Seg(rt[],rt[],p->s+);
int mid=s+t>>;
return k<=mid?
new Seg(build(p->l,s,mid,k),p->r,p->s+):
new Seg(p->l,build(p->r,mid+,t,k),p->s+);
}
int secret(Seg *p1,Seg *p2,Seg *p3,Seg *p4,int s,int t,int k){
while(s<t){
int mid=s+t>>;
int c=p1->l->s+p2->l->s-p3->l->s-p4->l->s;
if(k<=c)
t=mid,
p1=p1->l,
p2=p2->l,
p3=p3->l,
p4=p4->l;
else
k-=c,
s=mid+,
p1=p1->r,
p2=p2->r,
p3=p3->r,
p4=p4->r;
}
return d[s-];
}
inline int feel(int x,int y,int k){
int t=lca(x,y);
return secret(rt[id[x]],rt[id[y]],rt[id[t]],rt[id[fa[t]]],,d.size(),k);
}
int main(){
fread(B,,buf,stdin);
n=Rin(),q=Rin();
for(int i=;i<=n;i++)
val[i]=Rin(),d.push_back(val[i]);
sort(d.begin(),d.end());
d.erase(unique(d.begin(),d.end()),d.end());
for(int i=;i<d.size();i++)
h[d[i]]=i+;
for(int i=;i<=n;i++)
val[i]=h[val[i]];
for(int i=;i<n;i++){
int x=Rin(),y=Rin();
link(x,y);
}
dfs1();dfs2();
rt[]=nil;
rt[]->l=rt[]->r=rt[];
for(int i=;i<=n;i++)
rt[i]=build(rt[id[fa[rk[i]]]],,d.size(),val[rk[i]]);
while(q--){
int x=Rin(),y=Rin(),k=Rin();
printf("%d\n",ans=feel(x^ans,y,k));
}
return ;
}

ac倍增+主席树

注意root的深度不能设为0

#include<map>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=;
inline int Rin(){
int x=,c=getchar(),f=;
for(;c<||c>;c=getchar())
if(!(c^))
f=-;
for(;c>&&c<;c=getchar())
x=(x<<)+(x<<)+c-;
return x*f;
}
bool vis[N];
pair<int,int>v[N];
int n,m,ecnt,ans,fst[N],q[N],a[N*],dep[N],fa[N][],bin[],rt[N],tot,sum[N*],ls[N*],rs[N*];
void build(int &pr,int pl,int s,int t,int k){
pr=++tot;
sum[pr]=sum[pl]+;
if(!(s^t))return;
ls[pr]=ls[pl];
rs[pr]=rs[pl];
int mid=s+t>>;
if(k<=mid)build(ls[pr],ls[pl],s,mid,k);
else build(rs[pr],rs[pl],mid+,t,k);
}
struct edge{
int v,nxt;
}e[N<<];
inline void link(int x,int y){
e[++ecnt].v=y;
e[ecnt].nxt=fst[x];
fst[x]=ecnt;
}
void bfs(){
int hd=,tl=;
vis[]=;q[]=;
while(hd^tl){
int now=q[hd++];
build(rt[now],rt[fa[now][]],,n,a[now]);
for(int j=;j<=;j++)
if(bin[j]<=dep[now])
fa[now][j]=fa[fa[now][j-]][j-];
else
break;
for(int j=fst[now];j;j=e[j].nxt)
if(!vis[e[j].v])
vis[e[j].v]=,
fa[e[j].v][]=now,
dep[e[j].v]=dep[now]+,
q[tl++]=e[j].v;
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int j=;~j;j--)
if(dep[fa[x][j]]>=dep[y])
x=fa[x][j];
if(!(x^y))return x;
for(int j=;~j;j--)
if(fa[x][j]^fa[y][j])
x=fa[x][j],y=fa[y][j];
return fa[x][];
}
int query(int p1,int p2,int p3,int p4,int s,int t,int k){
if(!(s^t))return v[t].first;
int mid=s+t>>,c=sum[ls[p1]]+sum[ls[p2]]-sum[ls[p3]]-sum[ls[p4]];
if(k<=c)return query(ls[p1],ls[p2],ls[p3],ls[p4],s,mid,k);
return query(rs[p1],rs[p2],rs[p3],rs[p4],mid+,t,k-c);
}
int req(int x,int y,int k){
int t=lca(x,y);
return query(rt[x],rt[y],rt[t],rt[fa[t][]],,n,k);
}
int main(){
for(int i=;i<=;i++)
bin[i]=<<i;
n=Rin(),m=Rin();
for(int i=;i<=n;i++)
v[i].first=Rin(),v[i].second=i;
sort(v+,v++n);
for(int i=;i<=n;i++)
a[v[i].second]=i;
for(int i=;i<n;i++){
int x=Rin(),y=Rin();
link(x,y);link(y,x);
}
dep[]=;bfs();
for(int i=;i<=m;i++)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d",ans=req(x^ans,y,k));
if(i!=m)puts("");
}
return ;
}

可持久化线段树注意事项

1.对于较大的数据范围,用动态开点线段树时注意直接l+r>>1会爆,可以用l+r>>1=(l>>1)+(r>>1)+(l&r&1)

2.对于lca问题,根节点的深度统一设为1

3.树剖是O(2n)的,可能会超时,用倍增+宽搜可能稍稍快一些

4.我认为指针这种东西最好少用,处理不好可能RE

[bzoj2588][count on a tree] (主席树+lca)的更多相关文章

  1. 洛谷P2633/bzoj2588 Count on a tree (主席树)

    洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...

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

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

  3. SPOJ Count on a tree(主席树+LCA)

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

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

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

  5. BZOJ2588:Count on a tree(主席树)

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

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

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

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

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

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

  9. 【bzoj2588】Count on a tree 主席树

    这题给人开了个新思路. 原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间. 此题若带修改怎么办? 若对某个点的权值做修改,则这个点的子树都会受影响,想 ...

随机推荐

  1. Oracle使用SQL传输表空间

    源环境:RHEL 6.4 + Oracle 11.2.0.4 目的环境:RHEL 6.4 + Oracle 11.2.0.4 DG双机 要求:使用SQL传输表空间DBS_D_JINGYU从源环境到目的 ...

  2. 基于WebGL 的3D呈现A* Search Algorithm

    http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...

  3. Docker 基础 : 数据管理

    用户在使用 Docker 的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及容器的数据管理操作.容器中管理数据主要有两种方式:数据 ...

  4. java设计模式之简单工厂模式

    简单工厂: 简单工厂的优点: 1.去除客户端与具体产品的耦合,在客户端与具体的产品中增加一个工厂类,增加客户端与工厂类的耦合 2.封装工厂类,实现代码平台的复用性,创建对象的过程被封装成工厂类,可以多 ...

  5. Spark 入门

    Spark 入门 目录 一. 1. 2. 3. 二. 三. 1. 2. 3. (1) (2) (3) 4. 5. 四. 1. 2. 3. 4. 5. 五.         Spark Shell使用 ...

  6. C#开机自动启动程序代码

    新建一个winform拖一个checkbox进来.. 然后设置它的changed事件. 已经测试过,可以直接复制使用. private void checkBox1_CheckedChanged(ob ...

  7. Delphi_03_Delphi_Object_Pascal_基本语法_01

    这次是一个基本语法的第一部分,包括变量.变量初始化.常量.运算符.字符串等内容. { 本程序演示 Delphi Pascal 的基本语法 1.变量及变量的初始化 2.常量 3.运算符 3. 4. } ...

  8. JVM之内存结构

    JVM是按照运行时数据的存储结构来划分内存结构的.JVM在运行Java程序时,将他们划分成不同格式的数据,分别存储在不同的区域,这些数据就是运行时数据.运行时数据区域包括堆,方法区,运行时常量池,程序 ...

  9. spring源码:IOC(li)

    一.BeanDefinition BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式.创建最终的BeanDefinition主要包括两个步骤: 1)利用Bean ...

  10. 每次新建项目出现appcompat_v7 解决方法

    ADT升级版本后每次新建项目出现appcompat_v7 , 解决方案如下 问题生成: