Codeforces - High Cry

题目链接:Codeforces - High Cry


我们直接计算不合法的个数,也就是枚举每个点,当前点作为最大值的合法区间。

作为最大值的区间之间正反两次单调栈即可。

然后上一个异或>now的位置,我们可以对每一个二进制位递推预处理。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int L[N],R[N],n,a[N],f[30],s[N],top; long long res;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]); a[0]=2e9;
	for(int i=1;i<=n;i++){
		while(top&&a[s[top]]<a[i])	--top;
		L[i]=s[top]; s[++top]=i;
	}
	top=0;	a[n+1]=2e9; s[++top]=n+1;
	for(int i=n;i>=1;i--){
		while(top&&a[s[top]]<=a[i])	--top;
		R[i]=s[top]; s[++top]=i;
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<30;j++)	if(!(a[i]>>j&1))	L[i]=max(L[i],f[j]);
		for(int j=0;j<30;j++)	if(a[i]>>j&1)	f[j]=i;
	}
	for(int j=0;j<30;j++)	f[j]=n+1;
	for(int i=n;i>=1;i--){
		for(int j=0;j<30;j++)	if(!(a[i]>>j&1))	R[i]=min(R[i],f[j]);
		for(int j=0;j<30;j++)	if(a[i]>>j&1)	f[j]=i;
	}
	for(int i=1;i<=n;i++)	res+=1LL*(i-L[i])*(R[i]-i);
	cout<<1LL*n*(n+1)/2-res;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章