BZOJ2588: Spoj 10628. Count on a tree
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 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
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
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。
Source
题解:
感觉很好写。
想快一点于是写了离线的tarjan 求LCA,写完了发现bzoj强制在线T_T
代码:(应该有bug,因为没评测。。。)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 500+100 14 #define maxm 500+100 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define mod 1000000007 23 using namespace std; 24 inline int read() 25 { 26 int x=0,f=1;char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 29 return x*f; 30 } 31 struct edge{int go,next;}e[2*maxn]; 32 int n,m,tot,cnt,u[maxn],v[maxn],rk[maxn],a[maxn],id[maxn],b[maxn],fa[maxn],head[maxn]; 33 int sum[maxm],ls[maxm],rs[maxm],lca[maxn],root[maxn]; 34 vector<pa>q[maxn]; 35 bool vis[maxn]; 36 inline void insert(int x,int y) 37 { 38 e[++tot].go=y;e[tot].next=head[x];head[x]=tot; 39 e[++tot].go=x;e[tot].next=head[y];head[y]=tot; 40 } 41 void update(int l,int r,int x,int &y,int v) 42 { 43 y=++cnt; 44 sum[y]=sum[x]+1; 45 if(l==r)return; 46 ls[y]=ls[x];rs[y]=rs[x]; 47 int mid=(l+r)>>1; 48 if(v<=mid)update(l,mid,ls[x],ls[y],v);else update(mid+1,r,rs[x],rs[y],v); 49 } 50 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 51 void dfs(int x) 52 { 53 vis[x]=1; 54 for(int i=head[x],y;i;i=e[i].next) 55 if(!vis[y=e[i].go]) 56 { 57 update(1,n,root[x],root[y],b[y]); 58 dfs(y); 59 fa[y]=x; 60 } 61 int t=q[x].size(); 62 for0(i,t-1)if(vis[q[x][i].first])lca[q[x][i].second]=find(x); 63 } 64 inline bool cmp(int x,int y){return a[x]<a[y];} 65 int main() 66 { 67 freopen("input.txt","r",stdin); 68 freopen("output.txt","w",stdout); 69 n=read();m=read(); 70 for1(i,n)a[i]=read(),id[i]=i; 71 sort(id+1,id+n+1,cmp); 72 for1(i,n)b[id[i]]=i; 73 for1(i,n-1)insert(read(),read()); 74 for1(i,m) 75 { 76 u[i]=read();v[i]=read();rk[i]=read(); 77 q[u[i]].push_back(pa(v[i],i)); 78 q[v[i]].push_back(pa(u[i],i)); 79 } 80 for1(i,n)fa[i]=i; 81 update(1,n,0,root[1],b[1]); 82 dfs(1); 83 int ans=0; 84 for1(i,m) 85 { 86 int x=root[u[i]],y=root[v[i]],xx=root[lca[i]],yy=root[fa[lca[i]]],l=1,r=n,k=rk[i]; 87 while(l!=r) 88 { 89 int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1; 90 if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;} 91 else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;} 92 } 93 ans=l; 94 printf("%d\n",a[id[ans]]); 95 } 96 return 0; 97 }
在线的话其实没多大区别
直接在dfs的时候就可以把主席树、LCA的预处理做出来,然后就OK了。
代码:(刚开始没更新1RE了5.6次。。。)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 100000+1000 14 #define maxm 2000000+1000 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define mod 1000000007 23 using namespace std; 24 inline int read() 25 { 26 int x=0,f=1;char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 29 return x*f; 30 } 31 struct edge{int go,next;}e[2*maxn]; 32 int n,m,tot,cnt,a[maxn],id[maxn],b[maxn],head[maxn]; 33 int sum[maxm],ls[maxm],rs[maxm],root[maxn],f[maxn][18],dep[maxn]; 34 bool vis[maxn]; 35 inline void insert(int x,int y) 36 { 37 e[++tot].go=y;e[tot].next=head[x];head[x]=tot; 38 e[++tot].go=x;e[tot].next=head[y];head[y]=tot; 39 } 40 void update(int l,int r,int x,int &y,int v) 41 { 42 y=++cnt; 43 sum[y]=sum[x]+1; 44 if(l==r)return; 45 ls[y]=ls[x];rs[y]=rs[x]; 46 int mid=(l+r)>>1; 47 if(v<=mid)update(l,mid,ls[x],ls[y],v);else update(mid+1,r,rs[x],rs[y],v); 48 } 49 void dfs(int x) 50 { 51 for1(i,17) 52 if((1<<i)<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break; 53 for(int i=head[x],y;i;i=e[i].next) 54 if(!dep[y=e[i].go]) 55 { 56 dep[y]=dep[x]+1;f[y][0]=x; 57 update(1,n,root[x],root[y],b[y]); 58 dfs(y); 59 } 60 } 61 int lca(int x,int y) 62 { 63 if(dep[x]<dep[y])swap(x,y); 64 int t=dep[x]-dep[y]; 65 for0(i,17) 66 if(t&(1<<i))x=f[x][i]; 67 if(x==y)return x; 68 for3(i,17,0) 69 if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; 70 return f[x][0]; 71 } 72 inline bool cmp(int x,int y){return a[x]<a[y];} 73 int main() 74 { 75 freopen("input.txt","r",stdin); 76 freopen("output.txt","w",stdout); 77 n=read();m=read(); 78 for1(i,n)a[i]=read(),id[i]=i; 79 sort(id+1,id+n+1,cmp); 80 for1(i,n)b[id[i]]=i; 81 for1(i,n-1)insert(read(),read()); 82 insert(0,1); 83 dep[0]=1; 84 dfs(0); 85 int ans=0; 86 for1(i,m) 87 { 88 89 int x=read()^ans,y=read(),xx=lca(x,y),yy=f[xx][0],k=read(),l=1,r=n; 90 x=root[x];y=root[y];xx=root[xx];yy=root[yy]; 91 while(l!=r) 92 { 93 int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1; 94 if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;} 95 else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;} 96 } 97 ans=a[id[l]]; 98 printf("%d",ans); 99 if(i!=m)printf("\n"); 100 } 101 return 0; 102 }
这貌似和dfs序没什么关系啊。。。
主席树维护的是点x到根的权值情况。