CodeForce 1454 F. Array Partition

Posted carered

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForce 1454 F. Array Partition相关的知识,希望对你有一定的参考价值。

题目链接

https://codeforces.com/problemset/problem/1454/F
技术图片
技术图片

题意

把一段长度为(n)的区间分成三段, 每段长度不为(0), 要求第一段区间的最大值等于第三段区间的最大值等于中间区间的最小值。输出是否能划分并输出方案。

思路

可以枚举所有可能的答案, 那么对于每一种答案,他的出现次数必定大于(3)
我们可以用单调栈维护一下每个数左右的最大值/最小值的位置,并且统计每个数出现的位置(需要事先离散化一下).
假设当前答案为(x), 那么 (x) 第一次出现的位置左边必须没有比它大的数, 最后一次右边同理, 那么剩下中间出现的位置我们进行枚举。
中间出现的(x)作为最小值时离它左右俩边最近的最大值位置这段范围就是这个最小值控制的区间,只需要判断这个区间和第一次和最后一次出现位置控制的区间是否都有交集即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 50;
int ind[maxn], len;
inline int getid(const int &val){
    return lower_bound(ind + 1, ind + len + 1, val) - ind;
}
int getlen(int a[], int n){
    for(int i = 0;i <= n;i++){
        ind[i] = a[i];
    }
    sort(ind + 1, ind + n + 1);
    return unique(ind + 1, ind + n + 1) - ind - 1;
}
int st[maxn], Lmax[maxn], Rmax[maxn], Lmin[maxn], Rmin[maxn];
void getLmax(int a[], int n){//左边第一个大于a[i]的数
    int cnt = 0;
    st[0] = 0;
    for(int i = 1;i <= n;i++){
        while(cnt && a[i] >= a[st[cnt]]) cnt--;
        Lmax[i] = st[cnt];
        st[++cnt] = i;
    }
}
void getRmax(int a[], int n){//右边第一个大于a[i]的数
    int cnt = 0;
    st[0] = n + 1;
    for(int i = n;i >= 1;i--){
        while(cnt && a[i] >= a[st[cnt]]) cnt--;
        Rmax[i] = st[cnt];
        st[++cnt] = i;
    }
}
void getLmin(int a[], int n){//左边第一个小于a[i]的数
    int cnt = 0;
    st[0] = 0;
    for(int i = 1;i <= n;i++){
        while(cnt && a[i] <= a[st[cnt]]) cnt--;
        Lmin[i] = st[cnt];
        st[++cnt] = i;
    }
}
void getRmin(int a[], int n){//右边第一个小于a[i]的数
    int cnt = 0;
    st[0] = n + 1;
    for(int i = n;i >= 1;i--){
        while(cnt && a[i] <= a[st[cnt]]) cnt--;
        Rmin[i] = st[cnt];
        st[++cnt] = i;
    }
}
int a[maxn];
vector<int> v[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        for(int i = 1;i <= n;i++){
            cin >> a[i];
            v[i].clear();
        }
        len = getlen(a, n);
        for(int i = 1;i <= n;i++) a[i] = getid(a[i]);
        getLmax(a, n);
        getRmax(a, n);
        getLmin(a, n);
        getRmin(a, n);
        for(int i = 1;i <= n;i++){
            v[a[i]].push_back(i);
        }
        int ok = 0;
        for(int i = 1;i <= n;i++){
            int m = v[i].size();
            if(m < 3) continue;
            if(Lmax[v[i][0]] == 0 && Rmax[v[i][m - 1]] == n + 1){
                for(int j = 1;j < m - 1;j++){
                    int pos = v[i][j];
                    if(Lmin[pos] + 1 <= Rmax[v[i][0]] && Rmin[pos] - 1 >= Lmax[v[i][m - 1]]){
                        ok = 1;
                        cout << "YES" << endl;
                        int ansl = min(pos - 1, Rmax[v[i][0]] - 1);
                        int ansr = n - max(pos + 1, Lmax[v[i][m - 1]] + 1) + 1;
                        cout << ansl << " " << n - ansl - ansr << " " << ansr <<endl;
                        break;
                    }
                }
                if(ok) break;
            }
        }
        if(!ok) cout << "NO" << endl;
    }
    return 0;
}







以上是关于CodeForce 1454 F. Array Partition的主要内容,如果未能解决你的问题,请参考以下文章

[codeforces]Round #538 (Div. 2) F. Please, another Queries on Array?

洛谷——P1454 圣诞夜的极光

p1454 圣诞夜的极光

Codeforces1539 F. Strange Array(思维,线段树)

Codeforces Round #731 (Div. 3) F. Array Stabilization (GCD version)

Codeforces1579 F. Array Stabilization (AND version)(思维+bfs)