• 牛客练习赛66 E


    牛客练习赛66 E

    传送门

    题意:给你一个排列,问有多少个区间满足第一个数字是次小值,最后一个值是次大值。

    分析:考虑到次小值的约束,可行的右端点肯定是一个区间。即第一个小于它的值到第二个小于它的值(不包含)之间的所有位置。同理可以考虑次大值的约束。最终对于一个右端点来说,可行的左端点肯定也是一个区间值。现在考虑暴力枚举左端点,这个时候要考虑可行的右区间内,有多少个右端点可行的左区间是包含自己这个左端点的。这么暴力更新肯定是不行的。注意到一个左端点会对固定右区间的元素造成贡献,所以可以用两个端点的插入删除来代替这一个行为。并且在考虑到一个右端点时,考虑其可行区间内的区间和即可,这可以用一个BIT维护。

    #include<bits/stdc++.h>
    
    #define PB push_back
    #define MP make_pair
    #define fi first
    #define se second
    
    using namespace std;
    
    typedef pair<int,int> PII;
    
    typedef long long LL;
    
    inline int read(){
        int res=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){res*=10;res+=ch-'0';ch=getchar();}
    
        return res*f;
    }
    
    const int N = 1000005;
    
    int a[N], n, p[N][2], s[N][2];
    
    int mx[N][21], mn[N][21];
    
    int lg[N];
    
    vector<PII> G[N];
    
    
    struct fwk{
        int T[N];
    
        inline int lowbit(int x){return x&-x;}
    
        void add(int x, int v){
            while(x<=n){
                T[x]+=v;
                x+=lowbit(x);
            }
        }
    
        int getSum(int p){
            int res=0;
            while(p){
                res+=T[p];
                p-=lowbit(p);
            }
    
            return res;
        }
    
        int getSum(int l, int r){
            return getSum(r)-getSum(l-1);
        }
    
    };
    
    fwk bit;
    
    inline int askMin(int l, int r){
        int id=lg[r-l+1];
        return min(mn[l][id],mn[r-(1<<id)+1][id]);
    }
    
    inline int askMax(int l, int r){
        int id=lg[r-l+1];
        return max(mx[l][id],mx[r-(1<<id)+1][id]);
    }
    
    void get_pre(){
        for(int i=1;i<=n;++i){
            int l=i;
            for(int id=20;id>=0;--id){
               int tr=l+(1<<id);
               if(tr<=n&&askMin(i,tr)==a[i])l+=(1<<id);
            }
            if(l==n){
                p[i][0]=p[i][1]=-1;
                continue;
            }
            ++l;p[i][0]=l;
            int r=l;
            for(int id=20;id>=0;--id){
                int tr=r+(1<<id);
                if(tr<=n&&askMin(l+1,tr)>a[i])r+=(1<<id);
            }
            p[i][1]=r;
        }
    }
    
    void get_suf(){
        for(int i=1;i<=n;++i){
            int r=i;
            for(int id=20;id>=0;--id){
                int tl=r-(1<<id);
                if(tl>=1&&askMax(tl,i)==a[i])r-=(1<<id);
            }
            if(r==1){
                s[i][0]=s[i][1]=-1;
                continue;
            }
            --r;
            s[i][1]=r;
    
            int l=r;
            for(int id=20;id>=0;--id){
                int tl=l-(1<<id);
                if(tl>=1&&askMax(tl,r-1)<a[i])l-=(1<<id);
            }
    
            s[i][0]=l;
        }
    }
    
    
    int main(){
        n=read();
        for(int i=1;i<=n;++i)a[i]=read();
    
        for(int i=1;i<=n;++i)mx[i][0]=mn[i][0]=a[i];
    
        for(int id=1;id<=20;++id){
            for(int i=1;i+(1<<id)-1<=n;++i){
                mx[i][id]=max(mx[i][id-1],mx[i+(1<<id-1)][id-1]);
                mn[i][id]=min(mn[i][id-1],mn[i+(1<<id-1)][id-1]);
            }
        }
    
    
        lg[1]=0;
        for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
    
        get_pre();get_suf();
    
        LL ans=0;
    
        for(int i=1;i<=n;++i){
            if(p[i][0]==-1||p[i][1]==-1)continue;
            G[p[i][0]].PB(MP(i,1));
            G[p[i][1]+1].PB(MP(i,-1));
        }
    
        for(int i=1;i<=n;++i){
            for(auto it:G[i]){
                bit.add(it.fi,it.se);
            }
            if(s[i][0]==-1||s[i][1]==-1)continue;
            ans+=bit.getSum(s[i][0],s[i][1]);
        }
    
        printf("%lld",ans);
    
    
        return 0;
    }
    
    
  • 相关阅读:
    keypress事件
    input输入框(blur,change,focus)
    click点击以后添加新class,删除其余同名class
    强制数组并且匹配Array
    模拟鼠标事件
    简单的form操作
    鼠标滚轮事件(mousewheel、DOMMouseScroll)
    事件委托技术
    从程序员到项目经理:项目经理必须懂一点“章法”
    JavaScript项目优化总结
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13197060.html
Copyright © 2020-2023  润新知