• [CF1156E] Special Segments of Permutation


    Description

    给定一个长度为 (n) 的排列 (p),求有多少区间 ([l,r]) 满足 (p[l]+p[r]=max{p[i]}),其中 (l le i le r)

    Solution

    单调栈预处理出每个元素的控制区间(以它为最大值的区间)

    枚举最大值位置 (i),于是 (l in [l[i],i], r in [i,r[i]])

    考察两个区间的长度,在小的那个中枚举,则只需要检查差是否在大区间中出现

    用排列的逆来检查,值 (x)(p_l,...,p_r) 中出现,即 (l le I_x le r),其中 (I)(p) 的逆

    显然每个元素被枚举次数的上界为 (O(log n)),于是时间复杂度为 (O(n log n))

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 200005;
    const int dbg = 1;
    
    int p[N],n,inv[N],l[N],r[N];
    stack<int> s;
    
    bool check(int x,int l,int r)
    {
        if(x<0 || x>n) return 0;
        return l<=inv[x] && inv[x]<=r;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>p[i], inv[p[i]]=i;
    
        for(int i=1;i<=n;i++)
        {
            while(s.size() && p[s.top()]<p[i]) s.pop();
            if(s.size()) l[i]=s.top()+1;
            else l[i]=1;
            s.push(i);
        }
    
        while(s.size()) s.pop();
        for(int i=n;i>=1;--i)
        {
            while(s.size() && p[s.top()]<p[i]) s.pop();
            if(s.size()) r[i]=s.top()-1;
            else r[i]=n;
            s.push(i);
        }
    
        if(dbg)
        {
            cout<<"monostack output: "<<endl;
            for(int i=1;i<=n;i++) cout<<l[i]<<" ";
            cout<<endl;
            for(int i=1;i<=n;i++) cout<<r[i]<<" ";
            cout<<endl<<endl;
        }
    
        int ans=0;
    
        for(int i=1;i<=n;i++)
        {
            int pl,pr,ql,qr;
            if(i-l[i] < r[i]-i)
            {
                pl=l[i];
                pr=i;
                ql=i;
                qr=r[i];
            }
            else
            {
                pl=i;
                pr=r[i];
                ql=l[i];
                qr=i;
            }
    
            if(dbg)
            {
                cout<<"round "<<i<<": "<<pl<<","<<pr<<" "<<ql<<","<<qr<<endl;
            }
    
            int tans=0;
            for(int j=pl;j<=pr;j++)
            {
                if(check(p[i]-p[j],ql,qr))
                {
                    ++tans;
                }
            }
    
            ans+=tans;
            if(dbg) cout<<" + "<<tans<<" = "<<ans<<endl;
        }
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    subprocess 的 Popen用法
    subprocess之check_out用法
    Appium使用总结
    如何将pyqt5的qt-designer设计出来的 .ui 和 .qrc 文件转化成 .py 文件
    python serial模块使用,是pyserial而非serial
    基于 Tensorflow 实现 Mobilenet V1 并基于 CFAR-10 数据训练
    预测单词词性
    单词纠错系统
    Python深度学习 deep learning with Python
    书单
  • 原文地址:https://www.cnblogs.com/mollnn/p/13331571.html
Copyright © 2020-2023  润新知