首页 > 代码库 > BZOJ2588: Spoj 10628. Count on a tree

BZOJ2588: Spoj 10628. Count on a tree

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2
8
9
105
7

HINT

 




HINT:

N,M<=100000

暴力自重。。。

 

Source

鸣谢seter

题解:
感觉很好写。
想快一点于是写了离线的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 100000000013 #define maxn 500+10014 #define maxm 500+10015 #define eps 1e-1016 #define ll long long17 #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 100000000723 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 }
View Code

在线的话其实没多大区别

直接在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 }
View Code

这貌似和dfs序没什么关系啊。。。

主席树维护的是点x到根的权值情况。

 

BZOJ2588: Spoj 10628. Count on a tree