Description
Input
Output
包含n行,每行一个整数,即a每个前缀的能量值。
Sample Input
1 2 3 4 5
Sample Output
3
6
10
9
Solution
题意其实就是对数组的异或前缀和$a[i]$,对每个$i$求出最大$a[j]+(a[j]~xor~a[i])$。
既然是二进制,就考虑按位贪心得出$a[j]$的值。
假设$a[i]$当前一位为$1$,那么$a[j]$的这一位选$0$或者$1$对答案都是一样的。
如果$a[i]$当前一位为$0$,那么$a[j]$就这一位填$1$。这一位填了$1$,后面贪每一位的时候必须包含这一位的$1$,也就是超集。这玩意儿用高维前缀和预处理一下最靠前的超集的位置就好了。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (1<<20) 5 using namespace std; 6 7 int n,a[N],f[N]; 8 9 int main() 10 { 11 memset(f,0x7f,sizeof(f)); 12 scanf("%d",&n); 13 for (int i=1; i<=n; ++i) 14 { 15 scanf("%d",&a[i]); 16 a[i]^=a[i-1]; f[a[i]]=min(f[a[i]],i); 17 } 18 for (int i=0; i<20; ++i) 19 for (int j=0; j<(1<<20); ++j) 20 if (!(j&(1<<i))) f[j]=min(f[j],f[j^(1<<i)]); 21 for (int i=1; i<=n; ++i) 22 { 23 int ans=0,now=0; 24 for (int j=19; j>=0; --j) 25 if (a[i]&(1<<j)) ans+=(1<<j); 26 else if (f[now^(1<<j)]<=i) ans+=(1<<j)*2, now^=(1<<j); 27 printf("%d\n",ans); 28 } 29 }