zoukankan      html  css  js  c++  java
  • 51nod 1962区间计数(单调栈加二分)

    题目要求是求出两个序列中处于相同位置区间并且最大值相同的区间个数,我们最直观的感受就是求出每个区间的最大值,这个可以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[N][2],q[N][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
    ",ans);
    }
  • 相关阅读:
    Java中的内存分配机制
    javac程序的内存分配
    Linux/Ubuntu下解压命令
    Java跨平台原理
    Java数据类型中String、Integer、int相互间的转换
    Maven的安装、配置及使用入门
    Eclipse快捷键大全(转载)
    shell编程基础
    ubuntu 安装source insight
    ubuntu samba
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8075490.html
Copyright © 2011-2022 走看看