Wannafly Winter Camp 2020 Day 6G 单调栈 - 贪心

对于排列 \(p\),它的单调栈 \(f\) 定义为,\(f_i\) 是以 \(p_i\) 结尾的最长上升子序列的长度

先给定 \(f\) 中一些位置的值,求字典序最小的 \(p\) 使得它满足这些值

Solution

显然 \(f[1]=1\),考虑所有满足 \(f[x]=1\) 的位置 \(b_1,\dots,b_k\),一定有 \(p_{b_1}>p_{b_2}>\dots >p_{b_k}\)

由于 \(b_1=1\),我们要最小化 \(p_1\),所以填入 \(p_{b_i}=k-i+1\)

然后考虑所有 \(f[x]=2\) 的数,同理操作(注意第一个数仍然为最小),填入值加一个偏移即可

最后,对于 \(f\) 值没有给出的那些数,从左到右从小到大填入即可

#include <bits/stdc++.h>
using namespace std;

const int N = 105;
int n,t,s,f[N],p[N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--) {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>f[i];
        int sum=0;
        memset(p,0,sizeof p);
        for(int i=1;i<=n;i++) {
            stack<int> v;
            for(int j=1;j<=n;j++) if(p[j]==0) {
                f[j]=i;break;
            }
            for(int j=1;j<=n;j++) if(f[j]==i) v.push(j);
            while(v.size()) p[v.top()]=++sum, v.pop();
        }
        for(int i=1;i<=n;i++) if(p[i]==0) p[i]=++sum;
        for(int i=1;i<=n;i++) cout<<p[i]<<(n==i?"":" ");
        cout<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12365070.html