细节:1.x>>=1(=_遗漏)
2.数据范围以为不用开longlong结果要乘)(遇到longlong能全开直接优先全开,省考虑)
两个关键点:1.若通过遍历的方法遍历每个或最近(遇极端数据过不了)
所以采取手写或运算加标记一遍过(逐个记位细化来代替遍历)
2.以为是要所有或大于其中所有,即大于最大值,就按每个作为最大值的时候的贡献度来计算,因此需要每个数作为最大的最大区间来计算,这里单调栈的思想可以解决,用数组记录
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
long long a[maxn];
long long vis[35];
long long n,l[maxn],r[maxn],l1[maxn],r1[maxn],sta[maxn];
long long cnt;
int main ()
{
scanf("%I64d",&n);
for(int i=1;i<=n;++i)
{
scanf("%I64d",&a[i]);
r[i]=n+1;
}
for(long long i=1;i<=n;++i)
{
long long x=a[i];
for(long long k=1;k<=34;++k)
{
long long t=(x&1);
if(t==0)
{
l[i]=max(l[i],vis[k]);
}
else {
vis[k]=i;
}
x>>=1;
}
}
for(long long i=1;i<=34;++i)
vis[i]=n+1;
for(long long i=n;i>=1;--i)
{
long long x=a[i];
for(long long j=1;j<=34;++j)
{
long long t=(x&1);
if(t==0)
r[i]=min(r[i],vis[j]);
else {
vis[j]=i;
}
x>>=1;
}
}
long long top=0;
for(long long i=1;i<=n;++i)
{
while(top!=0&&a[sta[top]]<a[i]) r1[sta[top--]]=i-1;
l1[i]=sta[top]+1;
sta[++top]=i;
}
while(top!=0)
r1[sta[top--]]=n;
for(int i=1;i<=n;++i)
{
if(l[i]>=l1[i])
{
if(r1[i]>=r[i])
cnt+=((i-l1[i]+1)*(r1[i]-i+1)-(r[i]-i)*(i-l[i]));
else {
cnt+=(l[i]-l1[i]+1)*(r1[i]-i+1);
}
}
else {
if(r1[i]>=r[i])
{
cnt+=(r1[i]-r[i]+1)*(i-l1[i]+1);
}
}
}
printf("%I64d\n",cnt);
return 0;
}
不要考虑问题太细节琐碎,有时候小的问题统一想法确定一下就别再想了,多是大方面有错误才会wa