题意:判断区间内的与和,OJ 中题目描述貌似有问题。
题解:
第一种方法:线段树搞即可,注意 longlong 和输出格式。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const long long maxn = 1e5+10;
long long value[maxn<<4+1];
void PushUp (long long rt){
long long a = rt<<1;
long long b = rt<<1|1;
if(value[a] == -1)
value[rt] = value[b];
else if(value[b] == -1)
value[rt] = value[a];
else
value[rt] = value[a] & value[b];
}
void build(long long l,long long r, long long rt){
if(l == r){
scanf("%lld", &value[rt]);
return;
}
long long m = l + (r-l)/2;
build(lson);
build(rson);
PushUp(rt);
}
long long query(long long L,long long R,long long l,long long r,long long rt){
if(L <= l && R >= r) return value[rt];
long long m = l + (r-l)/2;
long long ans = -1;
if(L <= m){
if(ans == -1){
ans = query(L, R, lson);
}else ans &= query(L, R, lson);
}
if(R > m){
if(ans == -1){
ans = query(L, R, rson);
}else ans &= query(L, R, rson);
}
return ans;
}
int main(){
long long n, m;
while(scanf("%lld %lld", &n, &m) != EOF){
memset(value, -1, sizeof(value));
build(1, n, 1);
for(int j = 1; j <= m; j++){
long long a, b;
scanf("%lld %lld", &a, &b);
//flag = 1;
printf("%lldn", query(a, b, 1, n, 1));
}
printf("n");
}
return 0;
}
第二种方法:&运算,二进制位都是 1,结果为 1,否则为 0。因此我们可以存储所有位的二进制前缀和。若前缀和做差正好等于区间长度,则这位是 1,否则是 0。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
long long a[100005];
int sum[100005][65]; //sum[i][j]表示前i个数在第j位的和
int main(){
int n, m;
while(scanf("%d %d", &n, &m) != EOF){
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
for(long long bit = 1, num = 1; bit <= 63; bit++, num <<= 1){
sum[i][bit] = sum[i-1][bit] + ((a[i]&num)>0);
}
}
while(m--){
int l, r;
scanf("%d %d", &l, &r);
long long ans = 0;
for(long long i = 1, num = 1; i <= 63; i++, num <<= 1){
if(sum[r][i] - sum[l-1][i] == r-l+1){
ans += num;
}
}
printf("%lldn", ans);
}
cout << endl;
}
return 0;
}
交第二种方法时又被格式坑了。。。