BZOJ 5092 分割序列

82 篇文章 0 订阅
18 篇文章 0 订阅

Problem

BZOJ

Solution

f ( b , n ) = max ⁡ i = 0 n ( ( b 1 ⊕ b 2 ⊕ . . . ⊕ b i ) + ( b i + 1 ⊕ b i + 2 ⊕ . . . ⊕ b n ) ) f(b,n)=\max_{i=0}^n((b_1 \oplus b _2 \oplus...\oplus b_i)+(b_{i+1} \oplus b_{i+2} \oplus...\oplus b_n)) f(b,n)=i=0maxn((b1b2...bi)+(bi+1bi+2...bn))
转化一下
f ( b , i ) = max ⁡ j = 0 i ( p r e j + p r e j ⊕ p r e i ) f(b,i)=\max_{j=0}^i(pre_j+pre_j\oplus pre_i) f(b,i)=j=0maxi(prej+prejprei)
题目就转化为了对于每个 i i i,求出一个最优的 j ( j &lt; i ) j(j&lt;i) j(j<i)
我们思考一下对于一定的 x x x y y y要怎么样 y + y ⊕ x y+y\oplus x y+yx最大

对二进制下的单独一位进行考虑,会发现式子的真值表是这样的

x\y01
001
111

那么每一位都是独立的,从高到低贪心即可。那么我们就需要查询在是否存在一个 p ≤ i p\leq i pi p r e p pre_p prep是前几位贪心结果的超集,用高维前缀和解决。
时间复杂度 O ( ( v + n ) log ⁡ v ) O((v+n)\log v) O((v+n)logv)

Code

#include <cstring>
#include <cstdio>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=300010,maxm=1100000;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
int n,mx,l,N,ans,mi[25],a[maxn],f[maxm];
int main()
{
	read(n);mi[0]=1;
	for(int i=1;i<=20;i++) mi[i]=mi[i-1]<<1;
	memset(f,0x3f,sizeof(f));
	for(rg int i=1;i<=n;i++)
	{
		read(a[i]);a[i]^=a[i-1];
		getmin(f[a[i]],i);getmax(mx,a[i]);
	}
	for(N=1;N<=mx;N<<=1) ++l;
	for(int i=0;i<l;i++)
	  for(rg int j=0;j<N;j++)
	    if(!(j&mi[i]))
	      getmin(f[j],f[j|mi[i]]);
	for(rg int i=1;i<=n;i++)
	{
		ans=0;
		for(int j=l-1;~j;j--)
		  if(!(a[i]&mi[j])&&f[ans|mi[j]]<=i)
		    ans|=mi[j];
		printf("%d\n",ans+(ans^a[i]));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值