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

题解:
感觉很好写。
想快一点于是写了离线的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 }
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到根的权值情况。

 
posted @ 2014-10-04 18:14  ZYF-ZYF  Views(188)  Comments(0Edit  收藏  举报