http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1962
这道题谢了很久的;
但是很高兴最后还是调出来了;
虽然我的单调栈是没有写错的;
但是光会模板显然是没有什么用的;
这道题目我们维护两个单调栈;
都是从大到小的;
两个单调队列需要同时更新;
什么时候统计答案呢?
当一个元素要出栈的时候,我们可以计算出这个最大值的区间;
那么我们在另外一个栈里找到这个值,爷计算出最大区间;
那么我们算算l可取的范围,r可取的范围,直接计算答案就好了;
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=4e5+5;
int a[N][2],q[N][2],r[2];
int n,x,y;
Ll ans;
Ll out(int c,int v,int x,int y,int k){
int L=1,R=r[k],mid,ans=1e9;
while(R>=L){
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 (Ll)max(min(c,q[ans][k])-max(x*1ll,q[ans-1][k]+1ll)+1,0ll)*(y-max(c,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]);
r[1]=r[0]=q[1][0]=q[1][1]=1;
for(int i=2;i<=n;i++)
for(int j=0;j<=1;j++){
while(r[j]&&a[q[r[j]][j]][j]<=a[i][j])ans+=out(q[r[j]][j],a[q[r[j]][j]][j],q[r[j]-1][j]+1,i-1,j^1),r[j]--;
q[++r[j]][j]=i;
}
for(int i=1;i<=r[0];i++)ans+=out(q[i][0],a[q[i][0]][0],q[i-1][0]+1,n,1);
printf("%lld",ans);
}