zoukankan      html  css  js  c++  java
  • [RMQ] Codeforces 1454F Array Partition

    题目大意

    给你一个长为 (n(3leq nleq 2 imes 10^5)) 的数组 ({a_n}),问是否能把它分成三段,第一段的最大值等于第二段的最小值等于第三段的最大值。若能,输出方案。

    题解

    预处理每一个 (a_i) 在它之前最后一次作为前缀的最大值的位置 (pre[a[i]]),以及每一个 (a_i) 在它之后最后一次作为后缀的最大值的位置 (suf[a[i]])。遍历每一个 (a[i]),若 ([pre[a[i]]+1,suf[a[i]-1]]) 的区间最小值等于 (a[i]),则数组可分为 ([1,pre[a[i]]],[pre[a[i]]+1,suf[a[i]]-1],[suf[a[i]],N]) 这三段。使用 ST 表维护即可,时间复杂度 (O(Nlog N))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType &T){
        elemType X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        T=(w?-X:X);
    }
    
    template<typename elemType>
    struct ST{
        elemType dp[200005][20];
        int N;
        ST(int _N=0):N(_N){}
        void Init(elemType *data,int Len){
            N=Len;
            for(RG i=1;i<=N;i++)
                dp[i][0]=data[i];
            for(RG j=1;(1<<j)<=N;j++)
                for(RG i=1;i+(1<<j)-1<=N;i++)
                    dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
            return;
        }
        elemType Query(int L,int R){
            int K=log2(R-L+1);
            return min(dp[L][K],dp[R-(1<<K)+1][K]);
        }
    };
    ST<int> RMQ;
    map<int,int> pre,suf;
    int a[200010],pos[200010];
    int T,N;
    
    void Solve(){
        pre.clear();suf.clear();
        int mx=-1;
        for(int i=N;i>=1;--i){
            pos[i]=suf[a[i]];
            mx=max(mx,a[i]);
            suf[mx]=i;
        }
        mx=-1;
        for(int i=1;i<=N;++i){
            if(pre[a[i]] && pos[i]>i){
                int L=pre[a[i]],R=pos[i];
                if(RMQ.Query(L+1,R-1)==a[i]){
                    cout<<"YES"<<endl;
                    cout<<L<<" "<<R-L-1<<" "<<N-R+1<<endl;
                    return;
                }
            }
            mx=max(mx,a[i]);
            pre[mx]=i;
        }
        cout<<"NO"<<endl;
    }
    
    int main(){
        Read(T);
        while(T--){
            Read(N);
            for(int i=1;i<=N;++i)
                Read(a[i]);
            RMQ.Init(a,N);
            Solve();
        }
        return 0;
    }
    
  • 相关阅读:
    linux 防火墙管理
    自动化运维监控工具有哪些?常用的开源运维监控工具大全
    编程必备github代码仓库使用
    安全加密算法
    浅笑若风之高效工作流程
    jmeter压力测试工具使用
    ES扩容实战记录
    在5G+AI+CLCP下拉动互联网走向物联网
    设计模式之简单工厂模式
    设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/AEMShana/p/14040408.html
Copyright © 2011-2022 走看看