题意:对于一个长度为n的非负整数序列b_1,b_2,...,b_n,
定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b_2 xor...xor b_i)+(b_{i+1} xor b_{i+2} xor...xor b_n)) 其中xor表示按位异或(XOR)
给定一个长度为n的非负整数序列a_1,a_2,...,a_n,请计算a的每个前缀的能量值。
n<=3e5,0<=a[i]<=1e6
思路:补ccpc的题被卡了,导致5h比赛后面2h都没了,查题解发现要用高维前缀和,先刷几题了解一下
实际上对于i,预处理前缀xor和数组s,答案就是max s[i]+s[i]^s[j]
考虑从高到低逐位确定
如果s[i]当前位为1,则不管s[j]当前位为0或1贡献都是2^j
如果s[i]当前位为0,则s[j]当前位为1的贡献是2^(j+1),当前位为0的贡献是0
考虑如何快速判断是否存在高位不劣,当前位为1,低位随意的s[j](即超集)
预处理一个数组f[i],f[i]表示对于所有j,i是0的位置j是0/1,i是1的位置j是1,所有合法的j的最小出现下标
直接判断f[now+2^j]是否<=i即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 typedef vector<PII> VII; 10 //typedef pair<ll,ll>P; 11 #define N 310000 12 #define M 2000010 13 #define fi first 14 #define se second 15 #define MP make_pair 16 #define pb push_back 17 #define pi acos(-1) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 21 #define lowbit(x) x&(-x) 22 #define Rand (rand()*(1<<16)+rand()) 23 #define id(x) ((x)<=B?(x):m-n/(x)+1) 24 #define ls p<<1 25 #define rs p<<1|1 26 27 const ll MOD=1e9+7,inv2=(MOD+1)/2; 28 double eps=1e-6; 29 int INF=1e9; 30 int dx[4]={-1,1,0,0}; 31 int dy[4]={0,0,-1,1}; 32 33 int f[M],a[N]; 34 35 int read() 36 { 37 int v=0,f=1; 38 char c=getchar(); 39 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 40 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 41 return v*f; 42 } 43 44 int main() 45 { 46 int S=1<<20; 47 rep(i,0,S) f[i]=INF; 48 int n=read(); 49 rep(i,1,n) 50 { 51 a[i]=read(); 52 a[i]^=a[i-1]; 53 f[a[i]]=min(f[a[i]],i); 54 } 55 rep(i,0,19) 56 rep(j,0,S-1) 57 if(!(j>>i&1)) f[j]=min(f[j],f[j^(1<<i)]); 58 rep(i,1,n) 59 { 60 int ans=0,now=0; 61 per(j,19,0) 62 if(a[i]>>j&1) ans+=(1<<j); 63 else 64 { 65 if(f[now^(1<<j)]<=i) ans+=(1<<(j+1)),now^=(1<<j); 66 } 67 printf("%d ",ans); 68 } 69 return 0; 70 }