bzoj 2588: Spoj 10628. Count on a tree

DFS序在树上建出主席树,然后。。。。。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #define ll long long
  8 #define M 200009
  9 using namespace std;
 10 ll read()
 11 {
 12   ll x=0,f=1;
 13   char ch=getchar();
 14   for(;ch<'0'||ch>'9';ch=getchar())
 15     if(ch=='-')
 16       f=-1;
 17   for(;ch>='0'&&ch<='9';ch=getchar())
 18     x=x*10+ch-'0';
 19   return x*f;
 20 }
 21 int lc[M][20],head[M],next[M],u[M],cnt,n,m,v[M],v1[M],n1,deep[M],pos[M],num[M],T,root[M];
 22 int tot,lastans;
 23 struct data
 24 {
 25     int l,r,sum;
 26 }a[20*M];
 27 void jia(int a1,int a2)
 28 {
 29     next[++cnt]=head[a1];
 30     head[a1]=cnt;
 31     u[cnt]=a2;
 32 }
 33 void dfs(int x)
 34 {
 35     num[++T]=x;
 36     pos[x]=T;
 37     for(int i=1;(1<<i)<=deep[x];i++)
 38         lc[x][i]=lc[lc[x][i-1]][i-1];
 39     for(int i=head[x];i;i=next[i])
 40       if(u[i]!=lc[x][0])
 41       {
 42           deep[u[i]]=deep[x]+1;
 43           lc[u[i]][0]=x;
 44           dfs(u[i]);
 45       }
 46 }
 47 void geng(int l,int r,int x,int &y,int z)
 48 {
 49     y=++tot;
 50     a[y].sum=a[x].sum+1;
 51     if(l==r)
 52       return;
 53     a[y].l=a[x].l;
 54     a[y].r=a[x].r;
 55     int mid=(l+r)>>1;
 56     if(mid>=z)
 57         geng(l,mid,a[x].l,a[y].l,z);
 58     else
 59         geng(mid+1,r,a[x].r,a[y].r,z);
 60 }
 61 int lca(int a1,int a2)
 62 {
 63     if(deep[a1]<deep[a2])
 64         swap(a1,a2);
 65     int a3=deep[a1]-deep[a2];
 66     for(int i=0;i<=16;i++)
 67         if(a3&(1<<i))
 68           a1=lc[a1][i];
 69     for(int i=16;i>=0;i--)
 70         if(lc[a1][i]!=lc[a2][i])
 71       {
 72           a1=lc[a1][i];
 73           a2=lc[a2][i];
 74       }
 75     if(a1==a2)
 76         return a1;
 77     return lc[a1][0];
 78 }
 79 int cha(int u,int v,int t,int k)
 80 {
 81     int a1=root[pos[u]],a2=root[pos[v]],a3=root[pos[t]],a4=root[pos[lc[t][0]]];
 82     int l=1,r=n1-1,ans;
 83     for(;;)
 84       {
 85           if(l==r)
 86               return v1[l];
 87           int mid=(l+r)>>1;
 88           int a5=a[a[a1].l].sum+a[a[a2].l].sum-a[a[a3].l].sum-a[a[a4].l].sum;
 89           if(a5>=k)
 90             {
 91                 r=mid;
 92                 a1=a[a1].l;
 93                 a2=a[a2].l;
 94                 a3=a[a3].l;
 95                 a4=a[a4].l;
 96             }
 97           else
 98             {
 99                 k-=a5;
100                 l=mid+1;
101                 a1=a[a1].r;
102                 a2=a[a2].r;
103                 a3=a[a3].r;
104                 a4=a[a4].r;
105             }
106       }
107 }
108 int main()
109 {
110     n=read();
111     m=read(); 
112     for(int i=1;i<=n;i++)
113       v1[i]=v[i]=read();
114     sort(v1+1,v1+n+1);
115     n1=unique(v1+1,v1+n+1)-v1;
116     for(int i=1;i<=n;i++)
117       v[i]=lower_bound(v1+1,v1+n1,v[i])-v1;
118     for(int i=1;i<n;i++)
119       {
120           int a1=read(),a2=read();
121           jia(a1,a2);
122           jia(a2,a1);
123       }
124     dfs(1);
125     for(int i=1;i<=n;i++)
126       geng(1,n1-1,root[pos[lc[num[i]][0]]],root[i],v[num[i]]);
127     for(int i=1;i<=m;i++)
128       {
129           int u=read()^lastans,v=read(),k=read();
130           int t=lca(u,v);
131           printf("%d",lastans=cha(u,v,t,k));
132           if(i!=m)
133             printf("\n");
134       }
135     return 0;
136 }

 

posted @ 2016-06-26 20:09  xiw5  阅读(89)  评论(0编辑  收藏  举报