【51Nod1962】区间计数

来源:互联网 发布:java web 工作流引擎 编辑:程序博客网 时间:2024/06/03 18:51

两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下:

Ans:=Σni=1Σnj=i[max{Ai,Ai+1,…,Aj}=max{Bi,Bi+1,…,Bj}]

注:[ ]内表达式为真,则为1,否则为0.

1≤N≤3.5×1051≤Ai,Bi≤N

样例解释:
7个区间分别为:(1,4),(1,5),(2,4),(2,5),(3,3),(3,5),(4,5)
Input
第一行一个整数N
第二行N个整数Ai
第三行N个整数Bi
Output
一行,一个整数Ans
Input示例
5
1 4 2 3 4
3 2 2 4 1
Output示例
7

题解
维护两个单调栈,当一个数出栈时,以他为最大值的区间就确定了,然后去另一个栈中找到这个值,计算重叠区间即可。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<set>#include<ctime>#include<vector>#include<cmath>#include<algorithm>#include<map>#include<queue>#include<stack>#define mod 1000000007#define ll long long #define N 350005#define inf 0x7fffffffusing namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,a[N][2],q[N][2],r[N],pos[N][2];ll ans;ll calc(int p,int x,int l,int r,int j){    int P=pos[x][j];    if (P==0) return 0;    int L=q[P-1][j]+1,R=r;    P=q[P][j];    return max(0LL,(ll)min(R,r)-max(P,p)+1)*max(0LL,(ll)min(P,p)-max(L,l)+1); }int main(){    n=read();    for (int j=0;j<=1;j++)        for (int i=1;i<=n;i++)            a[i][j]=read();    for (int i=1;i<=n;i++)        for (int j=0;j<=1;j++)        {            while (a[q[r[j]][j]][j]<=a[i][j]&&r[j]>0)            {                ans+=calc(q[r[j]][j],a[q[r[j]][j]][j],q[r[j]-1][j]+1,i-1,j^1);                pos[a[q[r[j]][j]][j]][j]=0;                q[r[j]][j]=0;                r[j]--;            }            q[++r[j]][j]=i;            pos[a[i][j]][j]=r[j];        }    for(int i=1;i<=r[0];i++)ans+=calc(q[i][0],a[q[i][0]][0],q[i-1][0]+1,n,1);    printf("%lld",ans);    return 0;}
原创粉丝点击