码迷,mamicode.com
首页 > 其他好文 > 详细

【xsy1214】 异或路径(xorpath) 点分治+可持久化trie

时间:2018-07-29 13:01:44      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:nbsp   clu   bit   fine   c++   ==   min   ace   head   

题目大意:给你一棵$n$个点的树,每个点有一个点权$x$,问你所有路径中点权异或和最大的路径的异或和

数据范围:$n≤30000$,$x≤2^{31}-1$。

如果是边上有点权的话非常简单,直接一个$trie$就可以水过去了。

然而这题是点权,非常烦人。我们考虑用点分治去解决。

假设当前需要遍历的树的重心是$x$,我们开一个可持久化$trie$,我们用$son[x][i]$表示$x$的第$i$个儿子(我们假设总共有$p_x$个),将从$son[x][i]$出发的路径异或和加入第$[i,p_x]$个$trie$树中,当我们遍历出一条从$x$出发,经过$son[x][i]$的路径时,我们把这个路径的异或和放入第$i-1$个$trie$树中进行搜索。

我们已知点分治的时间复杂度是$O(n\ log\ n)$,由于这里面套了一个可持久化$trie$,那么时间复杂度就是$O(n\ log\ n\ log_2^{max{x}}$。

然后我的$trie$树出了锅,路径长度的最后一个二进制位没有被塞进$trie$中,然后成功$GG$

  1 #include<bits/stdc++.h>
  2 #define M 100005
  3 #define INF 19260817
  4 using namespace std;
  5 
  6 struct edge{int u,next;}e[M*2]={0}; int head[M]={0},Use=0;
  7 void add(int x,int y){Use++;e[Use].u=y;e[Use].next=head[x];head[x]=Use;}
  8 
  9 int num[M]={0},vis[M]={0};
 10 
 11 int siz[M]={0};
 12 
 13 void dfssiz(int x,int fa){
 14     siz[x]=1;
 15     for(int i=head[x];i;i=e[i].next)
 16     if(e[i].u!=fa&&vis[e[i].u]==0){
 17         dfssiz(e[i].u,x);
 18         siz[x]+=siz[e[i].u];
 19     }
 20 }
 21 int minn,minid;
 22 void dfsmax(int x,int fa,int fasiz){
 23     int maxn=fasiz-siz[x];
 24     for(int i=head[x];i;i=e[i].next)
 25     if(e[i].u!=fa&&vis[e[i].u]==0){
 26         dfsmax(e[i].u,x,fasiz);
 27         maxn=max(maxn,siz[e[i].u]);
 28     }
 29     if(maxn<minn) minn=maxn,minid=x;
 30 }
 31 
 32 int makeroot(int x){
 33     dfssiz(x,0);
 34     minn=INF; minid=0;
 35     dfsmax(x,0,siz[x]);
 36     return minid;
 37 }
 38 
 39 struct trie{
 40     int a[2];
 41 }a[M*20]={0};int root[M]={0},use=0;
 42 
 43 void add(int &x,int zhi,int wei){
 44     a[++use]=a[x]; x=use; int hh=0;
 45     if(wei<0) return;
 46     if((1<<wei)&zhi) hh=1;
 47     add(a[x].a[hh],zhi,wei-1);
 48 }
 49 int query(int x,int zhi,int wei){
 50     if(wei<0||x==0) return 0; 
 51     int hh=1,ans=0;
 52     if((1<<wei)&zhi) hh=0;
 53     if(!a[x].a[hh]) return query(a[x].a[hh^1],zhi,wei-1);
 54     else return (1<<wei)+query(a[x].a[hh],zhi,wei-1);
 55 }
 56 
 57 void dfsdis(int x,int fa,int hh,int cnt){
 58     hh^=num[x];
 59     add(root[cnt],hh,30);
 60     for(int i=head[x];i;i=e[i].next)
 61     if(e[i].u!=fa&&vis[e[i].u]==0){
 62         dfsdis(e[i].u,x,hh,cnt);
 63     }
 64 }
 65 
 66 int ans=0;
 67 
 68 void query(int x,int fa,int hh,int cnt){
 69     hh^=num[x];
 70     int now=query(root[cnt-1],hh,30);
 71     ans=max(ans,now);
 72     ans=max(ans,hh);
 73     for(int i=head[x];i;i=e[i].next)
 74     if(e[i].u!=fa&&vis[e[i].u]==0){
 75         query(e[i].u,x,hh,cnt);
 76     }
 77 }
 78 
 79 void calc(int x){
 80     int cnt=0;
 81     for(int i=head[x];i;i=e[i].next)
 82     if(vis[e[i].u]==0){
 83         cnt++; root[cnt]=root[cnt-1];
 84         dfsdis(e[i].u,x,0,cnt);
 85     }
 86     cnt=0;
 87     for(int i=head[x];i;i=e[i].next)
 88     if(vis[e[i].u]==0){
 89         cnt++;
 90         ans=max(ans,num[x]);
 91         query(e[i].u,x,num[x],cnt);
 92     }
 93     use=0; memset(root,0,(cnt+1)<<2);
 94 }
 95 
 96 void dfs(int x){
 97     x=makeroot(x); vis[x]=1; 
 98     calc(x);
 99     for(int i=head[x];i;i=e[i].next)
100     if(vis[e[i].u]==0) dfs(e[i].u);
101 }
102 
103 int main(){
104 //    freopen("in.txt","r",stdin);
105 //    freopen("out.txt","w",stdout);
106     int n; scanf("%d",&n);
107     for(int i=1;i<=n;i++) scanf("%d",num+i);
108     for(int i=1;i<n;i++){
109         int x,y; scanf("%d%d",&x,&y);
110         add(x,y); add(y,x);
111     }
112     dfs(1);
113     cout<<ans<<endl;
114 }

 

【xsy1214】 异或路径(xorpath) 点分治+可持久化trie

标签:nbsp   clu   bit   fine   c++   ==   min   ace   head   

原文地址:https://www.cnblogs.com/xiefengze1/p/9384740.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!