bzoj2588 Spoj 10628. Count on a tree
2017-01-19 20:19
302 查看
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 5105 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
28
9
105
7
HINT
N,M<=100000暴力自重。。。
正解:树上主席树
利用树上前缀和的思想来进行主席树的操作,用dfs序存储每个结点的信息,然后就是道主席树版子题了。。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf 1<<30 #define il inline #define RG register #define ll long long #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to; }g[200010]; int head[100010],size[100010],dep[100010],dfn[100010],top[100010],fa[100010],son[100010],a[100010],num[100010],hashh[100010],root[100010],sum[5000010],ls[5000010],rs[5000010],m,n,N,sz,tot,cnt,pre; il int gi(){ RG int x=0,q=0; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x; } il void ins(RG int from,RG int to){ g[++N]=(edge){head[from],to},head[from]=N; return; } il void insert(RG int l,RG int r,RG int x,RG int &y,RG int v){ y=++sz,sum[y]=sum[x]+1; if (l==r) return; ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1; if (v<=mid) insert(l,mid,ls[x],ls[y],v); else insert(mid+1,r,rs[x],rs[y],v); return; } il void dfs1(RG int x,RG int p){ dfn[x]=++cnt,dep[x]=dep[p]+1,fa[x]=p,size[x]=1; RG int v,mx=0; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (v==p) continue; dfs1(v,x); size[x]+=size[v]; if (size[mx]<size[v]) mx=v; } son[x]=mx; return; } il void dfs2(RG int x,RG int p,RG int anc){ insert(1,tot,root[dfn[p]],root[dfn[x]],lower_bound(hashh+1,hashh+tot+1,a[x])-hashh); top[x]=anc; if (son[x]) dfs2(son[x],x,anc); RG int v; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (v==p || v==son[x]) continue; dfs2(v,x,v); } return; } il int lca(RG int u,RG int v){ RG int t; while (top[u]!=top[v]){ if (dep[top[u]]<dep[top[v]]) t=u,u=v,v=t; u=fa[top[u]]; } if (dep[u]<dep[v]) return u; else return v; } il int query(RG int a,RG int b,RG int k){ RG int c=lca(a,b),d=fa[c],L=1,R=tot,mid,tmp; a=root[dfn[a]],b=root[dfn[b]],c=root[dfn[c]],d=root[dfn[d]]; while (L<R){ mid=(L+R)>>1,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; if (k<=tmp) R=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d]; else L=mid+1,k-=tmp,a=rs[a],b=rs[b],c=rs[c],d=rs[d]; } return hashh[L]; } il void work(){ n=gi(),m=gi(); for (RG int i=1;i<=n;++i) num[i]=a[i]=gi(); for (RG int i=1;i<n;++i){ RG int u=gi(),v=gi(); ins(u,v),ins(v,u); } sort(num+1,num+n+1); hashh[++tot]=num[1]; for (RG int i=2;i<=n;++i) if (num[i]!=num[i-1]) hashh[++tot]=num[i]; dfs1(1,0),dfs2(1,0,1); for (RG int i=1;i<=m;++i){ RG int u=gi(),v=gi(),k=gi(); pre=query(u^pre,v,k); printf("%d",pre); if (i!=m) printf("\n"); } return; } int main(){ File("chairtree"); work(); return 0; }
相关文章推荐
- BZOJ2588: Spoj 10628. Count on a tree
- BZOJ2588: Spoj 10628. Count on a tree
- BZOJ2588: Spoj 10628. Count on a tree
- BZOJ2588: Spoj 10628. Count on a tree
- bzoj2588 Spoj 10628. Count on a tree
- bzoj2588: Spoj 10628. Count on a tree
- bzoj2588 Spoj 10628. Count on a tree
- bzoj 2588 Spoj 10628. Count on a tree
- BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
- [bzoj2588][Spoj10628]Count on a tree_主席树
- 2588: Spoj 10628. Count on a tree (可持久化线段树)
- Spoj 10628. Count on a tree HYSBZ - 2588 (树链剖分+主席树)
- 【bzoj 2588】Spoj 10628. Count on a tree
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
- SPOJ 10628. Count on a tree
- BZOJ 2588 Spoj 10628. Count on a tree
- 【主席树】bzoj2588 Spoj 10628. Count on a tree
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
- 2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)
- [bzoj 2588] Spoj 10628. Count on a tree:函数式线段树