[TS-A1486][2013中国国家集训队第二次作业]树[树的重心,点分治]

首先考虑暴力,可以枚举每两个点求lca进行计算,复杂度O(n^3logn),再考虑如果枚举每个点作为lca去枚举这个点的子树中的点复杂度会大幅下降,如果我们将每个点递归考虑,每次计算过这个点就把这个点删掉,那么如果每次删掉的点是当前子树的重心,枚举点对的复杂度就只有O(logn),对于每次查询答案在trie树中找到时间复杂度基本可视为O(1),最后在分治同时考虑“关键点”即可。总复杂度O(nlogn)。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cmath>
  7 #include <ctime>
  8 
  9 using namespace std;
 10 
 11 struct Edge
 12 {
 13     int    to,next;
 14 }e[210000];
 15 
 16 int    n,k,Ans=-1;
 17 int    Size[110000],cnt,p[110000],f[110000],a[110000];
 18 bool    visited[110000];
 19 
 20 void    Add_edge(const int x,const int y)
 21 {
 22     e[++cnt].to=y;
 23     e[cnt].next=p[x];
 24     p[x]=cnt;
 25     return ;
 26 }
 27 
 28 struct Trie
 29 {
 30     private:
 31         int    c[110000][2];
 32         int    d[3500000];
 33         int    cnt,root;
 34 
 35     public:
 36         void    insert(const int val,const int flag)
 37         {
 38             int    pos=root,temp;
 39             for(int i=30;i>=0;--i)
 40             {
 41                 temp=!!(val&(1<<i));
 42                 if(!c[pos][temp])
 43                 {
 44                     c[pos][temp]=++cnt;
 45                     c[cnt][0]=c[cnt][1]=0;
 46                     d[cnt]=0;
 47                 }
 48                 d[pos]=max(d[pos],flag);
 49                 pos=c[pos][temp];
 50             }
 51             d[pos]=max(d[pos],flag);
 52             return ;
 53         }
 54 
 55         void    query(const int val,const int flag)
 56         {
 57             int    temp,num=0,pos=root;
 58             for(int i=30;i>=0;--i)
 59             {
 60                 temp=!(val&(1<<i));
 61                 if(c[pos][temp] && d[c[pos][temp]]+flag>=k)
 62                 {
 63                     pos=c[pos][temp];
 64                     num|=(1<<i);
 65                 }
 66                 else
 67                 {
 68                     if(!c[pos][temp^1] || d[c[pos][temp^1]]+flag<k)
 69                     {
 70                         num=-1;
 71                         break;
 72                     }
 73                     else    pos=c[pos][temp^1];
 74                 }
 75             }
 76             if(k<=flag)Ans=max(Ans,val);
 77             Ans=max(Ans,num);
 78         }
 79         
 80         void    clear()
 81         {
 82             root=1;
 83             cnt=1;
 84             c[root][0]=c[root][1]=0;
 85             d[root]=0,d[0]=0;
 86             return ;
 87         }
 88 }T;
 89 
 90 int    Dfs(const int S,const int fa)
 91 {
 92     Size[S]=1;
 93     for(int i=p[S];i;i=e[i].next)
 94     {
 95         if(e[i].to!=fa && !visited[e[i].to])
 96             Size[S]+=Dfs(e[i].to,S);
 97     }
 98     return Size[S];
 99 }
100 
101 void    Get(const int S,const int fa,int & Centre,int & tot,const int nn)
102 {
103     int    Max=0,i;
104 
105     for(i=p[S];i;i=e[i].next)
106     {
107         if(e[i].to!=fa && !visited[e[i].to])
108         {
109             Get(e[i].to,S,Centre,tot,nn);
110             Max=max(Max,Size[e[i].to]);
111         }
112     }
113     Max=max(Max,nn-Size[S]);
114     if(tot>Max)tot=Max,Centre=S;
115     return ;
116 }
117 
118 void    Query(const int S,const int fa,int A,int F)
119 {
120     A^=a[S];F+=f[S];
121     T.query(A,F);
122     for(int i=p[S];i;i=e[i].next)
123     {
124         if(e[i].to!=fa && !visited[e[i].to])
125             Query(e[i].to,S,A,F);
126     }
127     return ;
128 }
129 
130 void    Insert(const int S,const int fa,int A,int F)
131 {
132     A^=a[S];F+=f[S];
133     T.insert(A,F);
134     for(int i=p[S];i;i=e[i].next)
135     {
136         if(e[i].to!=fa && !visited[e[i].to])
137             Insert(e[i].to,S,A,F);
138     }
139     return ;
140 }
141 
142 void    TDC(const int S)
143 {
144     int    i,Centre;
145 
146     visited[S]=true;
147     for(i=p[S];i;i=e[i].next)
148     {
149         if(!visited[e[i].to])
150         {
151             int    tot=n+1;
152             Dfs(e[i].to,0);
153             Get(e[i].to,0,Centre,tot,Size[e[i].to]);
154             TDC(Centre);
155         }
156     }
157     T.clear();
158     for(i=p[S];i;i=e[i].next)
159     {
160         if(!visited[e[i].to])
161         {
162             Query(e[i].to,0,a[S],f[S]);
163             Insert(e[i].to,0,0,0);
164         }
165     }
166     T.query(a[S],f[S]);
167     visited[S]=false;
168     return ;
169 }
170 
171 int main()
172 {
173     int    i,x,y;
174 
175     scanf("%d%d",&n,&k);
176     for(i=1;i<=n;++i)scanf("%d",&f[i]);
177     for(i=1;i<=n;++i)scanf("%d",&a[i]);
178 
179     for(i=1;i<n;++i)
180     {
181         scanf("%d%d",&x,&y);
182         Add_edge(x,y);
183         Add_edge(y,x);
184     }
185 
186     TDC(1);
187 
188     printf("%d\n",Ans);
189 
190     return 0;
191 }

 

posted @ 2015-12-31 02:17  Gster  阅读(238)  评论(0编辑  收藏  举报