思路:
每次查询L - R的 最大连续子区间的或值
但是 我们都知道或的话 只会增加 不会减少
所以 L - R 的或值就是最大的子区间 然后再求与x的或值就ok了
但是 n=1e5 q=1e5
我们不能每次循环都暴力跑一边 那肯定是不行的
这里我们可以把他们拆成2进制 存放到二维数组里
a[][] 第一层为第i个数 第二层为i层及之前所有数在二进制第j位的和
比如 有3个数
1 2 3
拆成2进制为 00 10 11
那么a[1][0]=0 a[1][1]=0
a[2][0]=1 a[2[1]=0
a[3]0]=2 a[3][1] =1
总共就2^60 完全可以暴力拆解 最大60次
我们在求或值的时候 只需要
a[l] - a[r-1] 即可
就可以获得这个区间的二进制数
然后我们就可以根据第j位是否存在二进制数 来选择是否 sum+=pow(2,j)
总代码如下`
另外需要注意的是 我用内置的pow 会错误
所以用到了快速幂
#include <bits/stdc++.h>
using namespace std;
#define py cout << "YES\n";
typedef long long ll;
int a[100009][66];
int b[65];
ll c[100006];
//快速幂
ll quickPow(ll a, ll n){
ll ans = 1;
while(n>0){
if(n&1>0) //如果n的当前末位为1
ans *= a; //ans乘上当前的a
a *= a; //a自乘
n >>= 1; //n往右移一位,表示除以2
}
return ans;
}
int main(){
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
ll x;
cin>>x;
int cnt=0;
for(int j=0;j<=62;j++) a[i][j]+=a[i-1][j];
while(x){
a[i][cnt++]+=x%2;
x/=2;
}
}
for(int i=0;i<q;i++){
int l,r; ll x;
ll sum=0;
int t=0;
memset(b,0,sizeof(b));
cin>>l>>r>>x;
while(x){
b[t++]=x%2;
x/=2;
}
for(int j=0;j<=62;j++){
b[j]+=a[r][j]-a[l-1][j];
if(b[j]) sum+=quickPow(2,j);
// printf("%d,%d\n",j ,b[j]);
}
c[i]=sum;
}
for(int i=0;i<q;i++) cout<<c[i]<<'\n';
}