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

题目大意:给你一棵$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 }

 

转载于:https://www.cnblogs.com/xiefengze1/p/9384740.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,你遇到的问题是在发送HTTP POST请求时收到了403 Forbidden的错误。这个错误通常表示你没有限访问所请求的资源。 要解决这个问题,你可以采取以下步骤: 1. 首先,确保你的请求URL正确,并且你有限访问该URL。你可以尝试在浏览器直接访问该URL,看看是否能够成功访问。 2. 如果你确定URL是正确的,并且你有限访问,那么可能是你的请求缺少了必要的身份验证信息。你可以检查你的请求头是否包含了正确的身份验证信息,比如Token或用户名密码。 3. 另外,你还可以检查服务器端的配置,确保你的请求被正确地处理和授。你可以查看服务器的日志,以了解更多关于403错误的详细信息。 综上所述,当你收到403 Forbidden错误时,你应该首先检查URL和限,然后确保请求包含了正确的身份验证信息。如果问题仍然存在,你可以进一步检查服务器端的配置和日志,以找出问题的根本原因。 #### 引用[.reference_title] - *1* [kubeadm init报错10248...(The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz‘ failed)](https://blog.csdn.net/weixin_45969972/article/details/123529966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)](https://blog.csdn.net/xsy29000/article/details/103181267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值