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;
    }
    
  • 相关阅读:
    HDU 5441 离线处理 + 并查集
    [转载]HDU 3478 判断奇环
    POJ 1637 混合图的欧拉回路判定
    [转载] 一些图论、网络流入门题总结、汇总
    UVA 820 --- POJ 1273 最大流
    [转载 ]POJ 1273 最大流模板
    POJ 3041 -- 二分图匹配
    2014西安现场赛F题 UVALA 7040
    UVA 12549
    割点、桥(一点点更新)
  • 原文地址:https://www.cnblogs.com/AEMShana/p/14040408.html
Copyright © 2011-2022 走看看