首页 > 其他 > 详细

Nikitosh 和异或

时间:2021-06-05 22:09:30      阅读:35      评论:0      收藏:0      [点我收藏+]

题面

\(l_{i}\) 为以 \(i\) 为结尾的区间中最大的一段异或值,\(r_{i}\) 为以 \(i\) 为开头的区间中最大的一段异或值。

则有

\[l_{i}=\max\left(l[i-1],sum_{l-1}\oplus sum_{r}\right) \]

\[r_{i}=\max\left(r[i+1],sum_{l-1}\oplus sum_{r}\right) \]

\(sum_{i}\) 为异或前缀和,跟前缀和是差不多的,就是运算的方式改成了异或。

最后的答案则为

\[ans=\max\left(ans,l_{i}+r_{i+1}\right) \]

Code:

#include<cstdio>
#define MAX 400001
#define re register
namespace OMA
{
   int n;
   int l[MAX],r[MAX];
   int sum[MAX],num[MAX];
   struct Trie
   {
     int tot;
     int ch[MAX*31][2];
     void begin()
     {
       tot = 0;
       for(re int i=0; i<=n*31; i++)
       {
         for(re int j=0; j<=1; j++)
         { ch[i][j] = 0; }
       }
     }
     inline void insert(int x)
     {
       int u = 0;
       for(re int i=30; i>=0; i--)
       {
         int pos = (x>>i)&1;
         if(!ch[u][pos])
         { ch[u][pos] = ++tot; }
         u = ch[u][pos];
       }
     }
     inline int query(int x)
     {
       int u = 0,ans = 0;
       for(re int i=30; i>=0; i--)
       {
         int pos = (x>>i)&1;
         if(ch[u][pos^1])
         { u = ch[u][pos^1],ans += 1<<i; }
         else
         { u = ch[u][pos]; }
       }
       return ans;
     }
   }tree;
   inline int max(int a,int b)
   { return a>b?a:b; }
   inline int read()
   {
     int s=0,w=1; char ch=getchar();
     while(ch<‘0‘||ch>‘9‘){ if(ch==‘-‘)w=-1; ch=getchar(); }
     while(ch>=‘0‘&&ch<=‘9‘){ s=s*10+ch-‘0‘; ch=getchar(); }
     return s*w;
   }
   signed main()
   {
     n=read();
     int ans = 0;
     for(re int i=1; i<=n; i++)
     { num[i] = read(); }
     for(re int i=1; i<=n; i++)
     { tree.insert(sum[i] ^= sum[i-1]^num[i]); }
     for(re int i=1; i<=n; i++)
     { l[i] = max(l[i-1],tree.query(sum[i])); }
     tree.begin();
     for(re int i=1; i<=n; i++)
     { sum[i] = 0; }
     for(re int i=n; i>=1; i--)
     { tree.insert(sum[i] ^= sum[i+1]^num[i]); }
     for(re int i=n; i>=1; i--)
     { r[i] = max(r[i+1],tree.query(sum[i])); }
     for(re int i=1; i<n; i++)
     { ans = max(ans,l[i]+r[i+1]); }
     printf("%d\n",ans);
     return 0;
   }
}
signed main()
{ return OMA::main(); }

Nikitosh 和异或

原文:https://www.cnblogs.com/-OMA-/p/14853548.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!