http://acm.hdu.edu.cn/showproblem.php?pid=4737
题意:
给数组,
问有多少对区间的 或 值的和 <m
由于或值 是递增的,因此,可以预处理rmq,每次枚举起点i,二分
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=100000+500;
int h[maxn];
int mx[maxn][20];
int n,q;
int getOr(int x,int y)
{
return x|y;
}
void rmq_init()
{
int i,j;
for(j=1; j<=n; j++) mx[j][0]=h[j];
int m=floor(log((double)n)/log(2.0));
for(i=1; i<=m; i++)
{
for(j=n; j>0; j--)
{
mx[j][i]=mx[j][i-1];
if(j+(1<<(i-1))<=n) mx[j][i]=getOr(mx[j][i],mx[j+(1<<(i-1))][i-1]);
}
}
}
int rmq(int l,int r)
{
int m=floor(log((double)(r-l+1))/log(2.0));
int a=getOr(mx[l][m],mx[r-(1<<m)+1][m]);
return a; //a为最大值
}
map<int ,int >mp;
int main()
{
int tt,cas=0;
scanf("%d",&tt);
int m;
int cnt=1;
while (tt--)
{
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++)
scanf("%d",&h[i]);
rmq_init();
ll ans=0;
for (int i=1; i<=n; i++)
{
int l=i,r=n,ret=i-1;
while(l<=r)
{
int mid=(l+r)>>1;
if (rmq(i,mid)<m)
l=mid+1,ret=mid;
else r=mid-1;
}
ans+=ret-i+1;
}
printf("Case #%d: %lld\n",cnt++,ans);
}
}