您的位置:首页 > 其它

51nod 1962区间计数(单调栈加二分)

2017-12-20 19:36 190 查看

题目要求是求出两个序列中处于相同位置区间并且最大值相同的区间个数,我们最直观的感受就是求出每个区间的最大值,这个可以O(N)的求,利用单调栈求出每个数作为最大值能够覆盖的区间。

然后我们可以在进行单调栈的时候统计一下答案,怎么统计呢?就是在一个数列弹栈的时候在另一个数列的单调栈中找到这个数,然后分别算出两个数列中所对应的区间,然后统计一下左端点和右端点能够取到的所有位置利用乘法原理求一下即可。—— by VANE

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n;
typedef long long ll;
ll ans;
int a
[2],q
[2],s[2];
ll calc(int pos,int v,int l,int r,int k)
{
int L=1,R=s[k],mid,ans=1e9;
while(L<=R)
{
mid=L+R>>1;
if(a[q[mid][k]][k]==v) {ans=mid;break;}
if(a[q[mid][k]][k]>v) L=mid+1;
else R=mid-1;
}
if(ans==1e9) return 0;
return 1ll*max(min(pos,q[ans][k])-max(l,q[ans-1][k]+1)+1,0)*(r-max(pos,q[ans][k])+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i][0]);
for(int i=1;i<=n;++i) scanf("%d",&a[i][1]);
s[1]=s[0]=q[1][0]=q[1][1]=1;
for(int i=2;i<=n;++i)
for(int j=0;j<2;++j)
{
while(s[j]&&a[q[s[j]][j]][j]<=a[i][j]) ans+=calc(q[s[j]][j],a[q[s[j]][j]][j],q[s[j]-1][j]+1,i-1,j^1),s[j]--;
q[++s[j]][j]=i;
}
for(int i=1;i<=s[1];i++) ans+=calc(q[i][1],a[q[i][1]][1],q[i-1][1]+1,n,0);
printf("%lld\n",ans);
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: