zoukankan      html  css  js  c++  java
  • 「LOJ#10056」「一本通 2.3 练习 5」The XOR-longest Path (Trie

    #10056. 「一本通 2.3 练习 5」The XOR-longest Path

    题目描述

    原题来自:POJ 3764

    给定一棵 nnn 个点的带权树,求树上最长的异或和路径。

    输入格式

    第一行一个整数 nnn,接下来 n−1n-1n1 行每行三个整数 u,v,wu,v,wu,v,w,表示 u,vu,vu,v 之间有一条长度为 www 的边。

    输出格式

    输出一行一个整数,表示答案。

    样例

    样例输入

    4
    1 2 3
    2 3 4
    2 4 6

    样例输出

    7

    样例解释

    最长的异或和路径是 1→2→31 o 2 o 3123 ,它的长度是 3⨁4=73 igoplus 4=734=7。

    注意:结点下标从 111 开始到 NNN。

    注:x⨁yx igoplus yxy 表示 xxx 与 yyy 按位异或。

    数据范围与提示

    对于 100%100\%100% 的数据,1≤n≤105,1≤u,v≤n,0≤w<2311le nle 10^5,1le u, v le n,0 le w < 2^{31}1n105​​,1u,vn,0w<231​​

    题解

    首先对于树上两点路径的异或值,可以用一个树上前缀和维护。

     记$sum[x]$为$x$到祖先的异或和。

    由于异或有:$a ⨁ a = 0$

    所以如下图,在$sum[u] ⨁ sum[v]$时,lca以上的屎色线已经被消掉了。

    所以$ans=sum[u] ⨁ sum[v]$

     问题转化为:有1e5个数,要求其中两数异或的最大值。

    于是变为「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair (Trie

    于是这道题就可以由两道看起来离得很远的题拼起来而成了。

      1 编号     题目     状态     分数     总时间     内存     代码 / 答案文件     提交者     提交时间
      2 #231397     #10056. 「一本通 2.3 练习 5」The XOR-longest Path    Accepted     100     225 ms     10364 KiB     C++ / 1.8 K     qwerta     2018-10-16 16:53:15
      3 
      4 #include<iostream>
      5 #include<cstring>
      6 #include<cstdio>
      7 #include<cmath>
      8 using namespace std;
      9 inline int read()
     10 {
     11     char ch=getchar();
     12     int x=0;
     13     while(!isdigit(ch))ch=getchar();
     14     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
     15     return x;
     16 }
     17 const int MAXN=1e5+3;
     18 struct emm{
     19     int e,f,v;
     20 }a[2*MAXN];//用来建树
     21 int h[MAXN];
     22 int tot=0;
     23 void con(int x,int y,int l)//连树边
     24 {
     25     a[++tot].f=h[x];
     26     h[x]=tot;
     27     a[tot].e=y;
     28     a[tot].v=l;
     29     a[++tot].f=h[y];
     30     h[y]=tot;
     31     a[tot].e=x;
     32     a[tot].v=l;
     33     return;
     34 }
     35 int d[MAXN],w[MAXN];//记深度和前缀和
     36 void dfs(int x)//dfs遍历树
     37 {
     38     for(int i=h[x];i;i=a[i].f)
     39     if(!d[a[i].e])
     40     {
     41         w[a[i].e]=(w[x] xor a[i].v);
     42         d[a[i].e]=d[x]+1;
     43         dfs(a[i].e);
     44     }
     45     return;
     46 }
     47 struct ahh{
     48     int nxt[2];
     49 }tr[3200003];//Trie树
     50 int cnt=0;
     51 int b[33];//用来按位拆分
     52 void add(int x)
     53 {
     54     int j=-1;
     55     memset(b,0,sizeof(b));
     56     while(x)//拆二进制
     57     {
     58         b[++j]=x&1;
     59         x>>=1;
     60     }
     61     int k=0;
     62     for(int j=31;j>=0;--j)
     63     {
     64         if(!tr[k].nxt[b[j]])
     65           tr[k].nxt[b[j]]=++cnt;
     66         k=tr[k].nxt[b[j]];
     67     }
     68     return;
     69 }
     70 long long find(int x)//返回与x异或的最大结果
     71 {
     72     int j=-1;
     73     memset(b,0,sizeof(b));
     74     while(x)
     75     {
     76         b[++j]=x&1;
     77         x>>=1;
     78     }
     79     long long now=0;
     80     int k=0;
     81     for(int j=31;j>=0;--j)
     82     {
     83         if(tr[k].nxt[1-b[j]])//尽量往不一样的走
     84         {
     85             now+=(1<<j);
     86             k=tr[k].nxt[1-b[j]];
     87         }
     88         else k=tr[k].nxt[b[j]];
     89     }
     90     return now;
     91 }
     92 int main()
     93 {
     94     //freopen("a.in","r",stdin);
     95     int n=read();
     96     for(int i=1;i<n;++i)
     97     {
     98         int u=read(),v=read(),w=read();
     99         con(u,v,w);//连树边
    100     }
    101     int s=min(7,n);
    102     d[s]=1;
    103     dfs(s);
    104     long long ans=0;
    105     for(int i=1;i<=n;++i)
    106       add(w[i]);//加前缀和
    107     for(int i=1;i<=n;++i)
    108       ans=max(ans,find(w[i]));//记录答案
    109     cout<<ans;
    110     return 0;
    111 }
  • 相关阅读:
    判断回车键自动提交
    WCF开发使用证书文件配置基于自定义X509证书
    递归算法
    Web网站开发常用正则表达式
    WINDSOW2003 IIS配置后无法显示 ASP网页的问题
    如何写好软件开发需求文档
    Bitmap Drawable Canvas Paint比较
    Android开发:LayoutParams的用法
    华为投身互联网:吹了冲锋号 就要往前冲
    android 获取手机号问题
  • 原文地址:https://www.cnblogs.com/qwerta/p/9822673.html
Copyright © 2011-2022 走看看