[题解]SP57 SUPPER - Supernumbers in a permutation

思路

如果 \(a_i\) 在某一个最长上升子序列中,那么,这个最长上升子序列一定是形如 \(\dots,a_p,a_i,a_q,\dots\) 的。

发现 \(a_p < a_i < a_q\),那么以 \(a_p\) 结尾的一串一定是一个最长上升子序列,以 \(a_q\) 开头的一定也是一个最长上升子序列。

那么我们跑两次 LIS,求出以 \(a_i\) 结尾的 LIS,与以 \(a_i\) 开头 的 LIS,分别用 \(dp_{0/1}\) 表示。

对于一个可行的 \(a_i\) 一定有 \(dp_{0,i} + dp_{1,i} - 1 = ans\),其中 \(ans\) 表示 LIS 的长度。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 1e5 + 10,inf = 1e9 + 10;  
int n;  
int arr[N];  
int q[2][N],dp[2][N];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        if (c == EOF) exit(0);  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline void solve(){  
    memset(q,0,sizeof(q));  
    memset(dp,0,sizeof(dp));  
    q[1][0] = inf;  
    vector<int> v;  
    int ans1 = 0,ans2 = 0;  
    n = read();  
    for (re int i = 1;i <= n;i++) arr[i] = read();  
    for (re int i = 1;i <= n;i++){  
        int id = lower_bound(q[0] + 1,q[0] + ans1 + 1,arr[i]) - q[0];  
        q[0][id] = arr[i];  
        dp[0][i] = id;  
        ans1 = max(ans1,id);  
    }  
    for (re int i = n;i;i--){  
        if (arr[i] < q[1][ans2]){  
            dp[1][i] = ++ans2;  
            q[1][ans2] = arr[i];  
        }  
        else{  
            int l = 1,r = ans2;  
            while (l < r){  
                int mid = l + r >> 1;  
                if (q[1][mid] <= arr[i]) r = mid;  
                else l = mid + 1;  
            }  
            q[1][l] = arr[i];  
            dp[1][i] = l;  
            ans2 = max(ans2,l);  
        }  
    }  
    for (re int i = 1;i <= n;i++){  
        if (dp[0][i] + dp[1][i] - 1 == ans1) v.push_back(arr[i]);  
    }  
    sort(v.begin(),v.end());  
    printf("%d\n",(int)(v.size()));  
    for (auto x:v) printf("%d ",x);  
    puts("");  
}  
  
int main(){  
    while (1) solve();  
    return 0;  
}  
posted @ 2024-06-26 12:37  WBIKPS  阅读(41)  评论(0)    收藏  举报