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); }
相关文章推荐
- 51nod 1962 区间计数(单调栈+二分)
- 单调栈 51nod 1962 区间计数
- 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线
- 51Nod-1962-区间计数
- 51nod 1962 区间计数
- 51nod 第K大区间2(二分+树状数组)
- 51nod 40 第K大区间 二分+尺取
- 51nod 1686 第K大区间 二分好题
- ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)
- 51nod-1686 第K大区间(二分+尺取法)
- 51NOD 1810 连续区间 分治 区间计数
- 【二分+Two Pointers】51Nod 1686 第K大区间
- 51Nod【1686】——1686 第K大区间(尺取+二分)
- 51nod 1686 第K大区间【离散化+二分】
- 51nod 1686 第K大区间【离散化+二分】
- 51nod 1686-第K大区间(离散化+二分+尺取)
- 51nod 1279 扔盘子 【二分+区间优化】
- 51nod 1686 第K大区间(二分 尺取)
- 51nod1962:区间计数(分治 & 二分)
- 51nod 1686 第K大区间 (二分+滑动窗口+离散化)