BZOJ2588: Spoj 10628. Count on a tree
2014-10-04 18:14
357 查看
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 1795 Solved: 371
[Submit][Status]
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
HINT:N,M<=100000
暴力自重。。。
Source
鸣谢seter题解:
感觉很好写。
想快一点于是写了离线的tarjan 求LCA,写完了发现bzoj强制在线T_T
代码:(应该有bug,因为没评测。。。)
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<queue> #include<string> #define inf 1000000000 #define maxn 100000+1000 #define maxm 2000000+1000 #define eps 1e-10 #define ll long long #define pa pair<int,int> #define for0(i,n) for(int i=0;i<=(n);i++) #define for1(i,n) for(int i=1;i<=(n);i++) #define for2(i,x,y) for(int i=(x);i<=(y);i++) #define for3(i,x,y) for(int i=(x);i>=(y);i--) #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} return x*f; } struct edge{int go,next;}e[2*maxn]; int n,m,tot,cnt,a[maxn],id[maxn],b[maxn],head[maxn]; int sum[maxm],ls[maxm],rs[maxm],root[maxn],f[maxn][18],dep[maxn]; bool vis[maxn]; inline void insert(int x,int y) { e[++tot].go=y;e[tot].next=head[x];head[x]=tot; e[++tot].go=x;e[tot].next=head[y];head[y]=tot; } void update(int l,int r,int x,int &y,int v) { y=++cnt; sum[y]=sum[x]+1; if(l==r)return; ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)>>1; if(v<=mid)update(l,mid,ls[x],ls[y],v);else update(mid+1,r,rs[x],rs[y],v); } void dfs(int x) { for1(i,17) if((1<<i)<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break; for(int i=head[x],y;i;i=e[i].next) if(!dep[y=e[i].go]) { dep[y]=dep[x]+1;f[y][0]=x; update(1,n,root[x],root[y],b[y]); dfs(y); } } int lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); int t=dep[x]-dep[y]; for0(i,17) if(t&(1<<i))x=f[x][i]; if(x==y)return x; for3(i,17,0) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } inline bool cmp(int x,int y){return a[x]<a[y];} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read(); for1(i,n)a[i]=read(),id[i]=i; sort(id+1,id+n+1,cmp); for1(i,n)b[id[i]]=i; for1(i,n-1)insert(read(),read()); insert(0,1); dep[0]=1; dfs(0); int ans=0; for1(i,m) { int x=read()^ans,y=read(),xx=lca(x,y),yy=f[xx][0],k=read(),l=1,r=n; x=root[x];y=root[y];xx=root[xx];yy=root[yy]; while(l!=r) { int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1; if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;} else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;} } ans=a[id[l]]; printf("%d",ans); if(i!=m)printf("\n"); } return 0; }
View Code
这貌似和dfs序没什么关系啊。。。
主席树维护的是点x到根的权值情况。
相关文章推荐
- 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 主席树
- SPOJ 10628 COT - Count on a tree(在树上建立主席树)(LCA)
- BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树
- bzoj 2588: Spoj 10628. Count on a tree(树上主席树)
- BZOJ 2588==Spoj 10628. Count on a tree
- BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树
- [BZOJ2588][Spoj10628]Count on a tree(树上主席树)
- Spoj 10628. Count on a tree 树上主席树
- BZOJ 2588: Spoj 10628. Count on a tree
- BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- SPOJ 10628 Count on a tree (lca+主席树)
- HYSBZ2588-Spoj 10628. Count on a tree