bzoj 5092 [Lydsy1711月赛]分割序列——高维前缀和

Posted narh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 5092 [Lydsy1711月赛]分割序列——高维前缀和相关的知识,希望对你有一定的参考价值。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5092

套路地弄一个前缀异或和,就变成 f[ i ]=max_{j=0}^{i} { s[ j ] + (s[ i ]^s[ j ]) }。再套路地考虑按位贪心。

然后看了题解。按位贪心不是确定 f[ i ] 的这一位是0还是1,而是确定这一位是否给答案贡献 bin[ j ] !

按位考虑,自己这一位如果是1,则 j 不管取在哪,都只有一种情况,就是向答案贡献 bin[ j ];

  自己这一位如果是0,则 j 的位置影响到这一位对答案的贡献是 0 还是 2*bin[ j ] 。

因为自己这一位是0了,又要有那样的贡献,所以 j 的这一位一定是1;做到这一位的时候已经知道更高的位上选择了哪些位为1,所以如果知道自己位置是否可以在满足更高的选了1的位仍旧选1的基础上把这一位也选上1的话就好了。

这里有很好的思路:不是求自己能否达到,而是预处理整个数组里符合这个条件的最靠前的位置!这样自然也能判断自己是否可行了。

即,预处理满足更高位确定、当前位为1、更低位随便的a[ ]的最靠前位置。

这个可以用高维前缀和来做。初值是 p[ a[ i ] ]=min{ p[ a[ i ] ] , i } ,倒着枚举 i 就不用取min了;没有出现的值的 p 是 n+1 ,p[ 0 ] = 0。

状态里的 0 表示不作要求,1表示必须为1;则从低到高位枚举,p[ i ]对(最高位到当前位固定、当前位到最低位是自己子集)的p[ j ]取min即可。

计算答案的时候注意因为 a[ i ]&bin[ j ] 而产生贡献的,不用算在和 p 有关的那个限制里。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+5,M=25,K=(1<<20)+5;//K!=1e6!!!
int n,a[N],bin[M],p[K];
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>9||ch<0){if(ch==-)fx=0;ch=getchar();}
  while(ch>=0&&ch<=9) ret=(ret<<3)+(ret<<1)+ch-0,ch=getchar();
  return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
int main()
{
  int mx=0,lm;
  n=rdn();for(int i=1;i<=n;i++)a[i]=rdn()^a[i-1],mx=Mx(mx,a[i]);
  bin[0]=1;
  for(lm=1;(bin[lm-1]<<1)<=mx;lm++)
    bin[lm]=bin[lm-1]<<1;
  bin[lm]=bin[lm-1]<<1;
  for(int i=1;i<bin[lm];i++)p[i]=n+1;
  for(int i=n;i;i--)p[a[i]]=i;
  p[0]=0;
  for(int t=0;t<lm;t++)
    for(int i=1;i<bin[lm];i++)
      if(!(i&bin[t]))
    p[i]=Mn(p[i],p[i|bin[t]]);
  for(int i=1,ans=0,lj=0;i<=n;i++,ans=0,lj=0)
    {
      for(int j=lm-1;j>=0;j--)
    {
      if(a[i]&bin[j])
        {ans+=bin[j];continue;}//no lj|=bin[j]
      if(p[lj|bin[j]]<=i)
        {
          ans+=bin[j]<<1;lj|=bin[j];
        }
    }
      printf("%d
",ans);
    }
  return 0;
}

 

以上是关于bzoj 5092 [Lydsy1711月赛]分割序列——高维前缀和的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 5093: [Lydsy1711月赛]图的价值

bzoj 5094 [Lydsy1711月赛]硬盘检测 概率dp

bzoj 5093 [Lydsy1711月赛]图的价值 NTT+第二类斯特林数

bzoj5093[Lydsy1711月赛]图的价值(NTT+第二类斯特林数)

bzoj 5092 分割序列 —— 高维前缀和

bzoj 5091: [Lydsy0711月赛]摘苹果