题目描述
给定一个长度为n的数组a,并给出q次询问,每次询问给出三个数,分别是l,r,x。
在a数组中l到r这个区间里找到 连续子序列 的相或 ( | ) 的值再或 ( | ) 上x,让其值最大,并输出这个值
数组下标从1开始
连续子序列为从数组开头删除若干个数,数组末尾删除若干个数得到的结果
例如 对于[3,4,8,5,9,7]这个数组来说,[3,4],[8,5,9]是它的连续子序列,[3,8,5],[4,7]则不是
输入描述:
第一行为n和q
第二行有n个非负整数,分别为a1 ,a2,a3 ,...,an
接下来有q行每行分别有三个数表示该次询问的l,r,x
1≤n≤1e5
1≤q≤1e5
1<=l<=r<=n
0<=x<=2^60−1
对任意的 i(1≤i≤n), 1≤ai≤2^60−1
输出描述:
输出q行,第i行代表第i次询问的答案
示例1
输入
5 5
4 11 8 2 2
3 4 5
1 1 13
1 1 17
1 4 5
1 1 8
输出
15
13
21
15
12
解题思路
把每一位数都以二进制的形式进行前缀和存储
cpp
#include<iostream>
using namespace std;
#define int long long
const int N=1e5+10;
int a[N];
int sum[N][100];
signed main(){
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=0;j<64;j++){
//判断a[i]的二进制位的每一位是否为一,这一位的前缀和就加一
sum[i][j]=sum[i-1][j]+(a[i]>>j&1);
}
}
while(q--){
int l,r,k;
cin>>l>>r>>k;
int ans=0;
for(int i=0;i<64;i++){
//判断减去l-1的前缀和后的i位是否大于0,如果大于0就把ans的第i位变为1
if(sum[r][i]-sum[l-1][i])ans|=(long long)1<<i;
}
ans=ans|k;
cout<<ans<<endl;
}
return 0;
}