BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

题意:

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

分析:

每个结点开线段树,保存到根这段路径上的权值,然后类似树上差分在主席树上求第k小

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
int head[N],to[N<<1],nxt[N<<1];
int top[N],fa[N],dep[N],son[N],siz[N],tot,cnt;
int n,m,root[N],t[N*50],ls[N*50],rs[N*50],a[N],see;
struct A{
int num,id,v;
}d[N];
bool cmp1(const A &x,const A &y){return x.num<y.num;}
bool cmp2(const A &x,const A &y){return x.id<y.id;}
inline void add(int u,int v){
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void rd(int &x){
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f;
}
void dfs1(int x){
siz[x]=1;
for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]){
fa[to[i]]=x;dep[to[i]]=dep[x]+1;
dfs1(to[i]);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]])son[x]=to[i];
}
}
void dfs2(int x,int t){
top[x]=t;
if(son[x])dfs2(son[x],t);
for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]&&to[i]!=son[x])dfs2(to[i],to[i]);
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]])swap(x,y);
y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
void insert(int x,int &y,int l,int r,int val){
y=++tot;
if(l==r){t[y]=t[x]+1;return ;}
int mid=l+r>>1;
if(val<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,val);
else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,val);
t[y]=t[ls[y]]+t[rs[y]];
}
int query(int x,int y,int lca,int f,int l,int r,int k){
if(l==r)return a[l];
int mid=l+r>>1,sizls=t[ls[x]]+t[ls[y]]-t[ls[lca]]-t[ls[f]];
if(k<=sizls) return query(ls[x],ls[y],ls[lca],ls[f],l,mid,k);
else return query(rs[x],rs[y],rs[lca],rs[f],mid+1,r,k-sizls);
}
void build(int x){
for(int i=head[x];i;i=nxt[i]){
if(to[i]!=fa[x]){
insert(root[x],root[to[i]],1,n,d[to[i]].v);
build(to[i]);
}
}
}
int main(){
rd(n);rd(m);
int i,x,y,k,j;
for(i=1;i<=n;i++) rd(d[i].num),d[i].id=i;
sort(d+1,d+n+1,cmp1);
d[0].num=-1000000;
for(j=0,i=1;i<=n;i++){if(d[i].num!=d[i-1].num)j++;d[i].v=j;a[j]=d[i].num;}
sort(d+1,d+n+1,cmp2);
for(i=1;i<n;i++) {
rd(x);rd(y);
add(x,y);add(y,x);
}
dep[1]=1;fa[1]=0;
dfs1(1);dfs2(1,1);
int ans=0;
//for(i=1;i<=n;i++) insert(root[fa[a[i]]],root[a[i]],minn,maxn,v[a[i]]);
insert(root[0],root[1],1,n,d[1].v);
build(1);
for(i=1;i<=m;i++) {
scanf("%d%d%d",&x,&y,&k);x^=ans;
int lca=LCA(x,y);
ans=query(root[x],root[y],root[lca],root[fa[lca]],1,n,k);
if(i<m)
printf("%d\n",ans);
else printf("%d",ans);
}
}
上一篇:android Handler机制详解


下一篇:基于UDP协议的网络编程