Luogu P1704 寻找最优美做题曲线

题目传送门

额……因为没考虑好题目条件的关系,\(WA\)了好几次……


把必须要做题的\(K\)天看作一个个端点

因为这\(K\)天是我们必须要做题的,而我们又要保证做题数量单调递增,所以我们可以在每两个端点之间筛选出大于左端点小于右端点的数,然后整体跑一遍最长上升子序列,这样就可以保证满足题目条件

无解的情况就是存在一个右端点大于等于右端点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define LL long long
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
int p[500010], a[500010], ans[500010], b[500010], tot;
int main() {
    int n = read(), k = read();
    for(int i = 1; i <= k; ++i) p[i] = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    sort(p+1, p+k+1);
    for(int i = 1; i <= p[1]; ++i)
        if(a[i] < a[p[1]]) ans[++tot] = a[i];
    ans[++tot] = a[p[1]];
    for(int i = 2; i <= k; ++i) {
        if(a[p[i-1]] >= a[p[i]]) {
            printf("impossible\n"); return 0;
        }
        for(int j = p[i-1]+1; j <= p[i]; ++j) {
            if(a[j] < a[p[i]] && a[j] > a[p[i-1]]) ans[++tot] = a[j];
        }
        ans[++tot] = a[p[i]];
    }
    for(int i = p[k]; i <= n; ++i)
        if(a[i] > a[p[k]]) ans[++tot] = a[i];
    int cnt = 0;
    for(int i = 1; i <= tot; ++i) {
        if(ans[i] > b[cnt]) b[++cnt] = ans[i];
        else {
            int pos = lower_bound(b+1, b+cnt+1, ans[i]) - b;
            b[pos] = ans[i];
        }
    }
    cout << cnt << endl;
    return 0;
}
posted @ 2019-11-14 10:31  MorsLin  阅读(111)  评论(0编辑  收藏  举报