codeforce 686div3 F Array Partition單調棧

沒名字-tw發表於2020-11-26

Array Partition

You are given an array a consisting of n integers.

Let min(l,r) be the minimum value among al,al+1,…,ar and max(l,r) be the maximum value among al,al+1,…,ar.

Your task is to choose three positive (greater than 0) integers x, y and z such that:

x+y+z=n;
max(1,x)=min(x+1,x+y)=max(x+y+1,n).
In other words, you have to split the array a into three consecutive non-empty parts that cover the whole array and the maximum in the first part equals the minimum in the second part and equals the maximum in the third part (or determine it is impossible to find such a partition).

Among all such triples (partitions), you can choose any.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (3≤n≤2⋅105) — the length of a.

The second line of the test case contains n integers a1,a2,…,an (1≤ai≤109), where ai is the i-th element of a.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each test case, print the answer: NO in the only line if there is no such partition of a that satisfies the conditions from the problem statement. Otherwise, print YES in the first line and three integers x, y and z (x+y+z=n) in the second line.

If there are several answers, you can print any.

Example
input
6
11
1 2 3 3 3 4 4 3 4 2 1
8
2 9 1 7 3 9 4 1
9
2 1 4 2 4 3 3 1 2
7
4 2 1 1 4 1 4
5
1 1 1 1 1
7
4 3 4 3 3 3 4
output
YES
6 1 4
NO
YES
2 5 2
YES
4 1 2
YES
1 1 3
YES
2 1 4
後悔沒看這題…我是真的菜,反而去做了前面那道題,後來賽後看著題,第一反應就是單調棧,只需要列舉每個點作為中間部分的最小值的情況,那麼通過單調棧求出這個數做為最小值的最大連續區間的位置(當然要考慮相等的情況,很明顯只要不是這個數的第一個數或者最後一個數我們就能把他從棧裡面拿走,用map標記一下就好了),這樣貪心的選取,再根據左右區間的最值比較就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int num[N];
int fmmax[N];
int rmax[N];
int l[N];
int r[N];
int book[N];
int state[N];
int main ()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        map<int,int>mp;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>num[i];
            fmmax[i]=0;
            rmax[i]=0;
            if(mp[num[i]]==0)
            {
                book[i]=1;
                mp[num[i]]=1;
            }
            else book[i]=0;
        }
        map<int,int>mmap;
        for(int i=n;i>=1;i--)
        {
            if(mmap[num[i]]==0)
            {
                state[i]=1;
                mmap[num[i]]=1;
            }
            else state[i]=0;
        }
        rmax[n+1]=0;
        for(int i=1;i<=n;i++)
        {
            fmmax[i]=max(num[i],fmmax[i-1]);
        }
        for(int i=n;i>=1;i--)
        {
            rmax[i]=max(num[i],rmax[i+1]);
        }
        stack<pair<int,int> >s;
        for(int i=1;i<=n;i++)
        {
            while(!s.empty()&&(s.top().first>num[i]||(s.top().first==num[i]&&!book[s.top().second])))
            {
                s.pop();
            }
            if(!s.empty())l[i]=s.top().second;
            else l[i]=0;
            s.push(make_pair(num[i],i));
        }
        while(!s.empty())s.pop();
        for(int i=n;i>=1;i--)
        {
            while(!s.empty()&&(s.top().first>num[i]||(s.top().first==num[i]&&!state[s.top().second])))
            {
                s.pop();
            }
            if(!s.empty())r[i]=s.top().second;
            else r[i]=n+1;
            s.push(make_pair(num[i],i));
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(fmmax[l[i]]==num[i]&&num[i]==rmax[r[i]])
            {
                ans=1;
                cout<<"YES"<<endl;
                cout<<l[i]<<' '<<r[i]-l[i]-1<<' '<<n-r[i]+1<<endl;
                break;
            }
        }
        if(!ans)cout<<"NO"<<endl;
    }
    return 0;
}

相關文章