BZOJ 5092 分割序列
阿新 • • 發佈:2019-01-04
Problem
Solution
轉化一下
題目就轉化為了對於每個
,求出一個最優的
我們思考一下對於一定的
,
要怎麼樣
最大
對二進位制下的單獨一位進行考慮,會發現式子的真值表是這樣的
x\y | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 1 |
那麼每一位都是獨立的,從高到低貪心即可。那麼我們就需要查詢在是否存在一個
且
是前幾位貪心結果的超集,用高維字首和解決。
時間複雜度
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;
}