https://www.luogu.com.cn/problem/T575379?contestId=233561
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
using ll = long long;
using pii = pair<int, int>;
const double PI = acos(-1);
const int N =1e6+10;
const int mod = 1e9 + 7;
ll a[N];
int dp[N][35];//dp数组存的从1-i,最近的一个大于2^j的数的下标
ll pre[N];
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=pre[i-1]^a[i];
}
for(int j=0;j<30;j++)
for(int i=1;i<=n;i++){
if(a[i]<((ll)1<<j)){
dp[i][j]=dp[i-1][j];//
}
else{
dp[i][j]=i;//a[i]>=2^j,等于当前的索引
}
}
a[0]=((ll)1<<30)-1;//a[0]要特殊处理
int q;cin>>q;
for(int k=1;k<=q;k++){
ll x;cin>>x;
int end=n+1;//考虑不存在的情况,为1的情况
for(int i=29;i>=0;i--){
if(((x>>i)&1)==1){
int now=dp[end-1][i];//1-(end-1)中找到最近的一个>=2^i的数
x^=pre[end-1]^pre[now];//求x异或now到(end-1)的值
if(x<a[now]){//当前的a[now]最高位可能为1,也可能没找到
end=now+1;//end存一下答案
break;
}
else{
x^=a[now];
end=now;//更新一下求异或值的右边界
}
}
}
cout<<end<<" ";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin>>T;
while (T--) {
solve();
}
return 0;
}
题解:
x=1010
1___ 0100 0110 0111 倒着找到这样的1___,(后面全为0的是一定成立的)然后更新x,再循环找,找到最小的c