bzoj 1047

来源:互联网 发布:cisco 端口隔离 编辑:程序博客网 时间:2024/04/30 15:00


求字典序最小,可以想到反向做最长下降子序列,求出 fi ,以 ai 为起始的最长上升子序列长度。


如果询问的长度 L 大于 最长上升子序列长度,直接输出 Impossible


贪心,因为要求字典序最小,对于满足条件 fiL 的最小的 iai 一定是上升序列的首位,

然后在序列的区间 [i+1,n] 内求出长度为 L1,且首位 aj>ai 的上升序列,递归处理即可。

正确性显然,实现可以非递归。


#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <vector>#include <utility>#include <stack>#include <queue>#include <iostream>#include <algorithm>template<class Num>void read(Num &x){    char c; int flag = 1;    while((c = getchar()) < '0' || c > '9')        if(c == '-') flag *= -1;    x = c - '0';    while((c = getchar()) >= '0' && c <= '9')        x = (x<<3) + (x<<1) + (c-'0');    x *= flag;    return;}template<class Num>void write(Num x){    if(x < 0) putchar('-'), x = -x;    static char s[20];int sl = 0;    while(x) s[sl++] = x%10 + '0',x /= 10;    if(!sl) {putchar('0');return;}    while(sl) putchar(s[--sl]);}#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)const int maxn = 1e4 + 5, INF = 0x3f3f3f3f;int n, m, a[maxn], f[maxn], LIS ,L;void init(){    read(n);    REP(i, 1, n) read(a[i]);}void prework(){    static int max[maxn];    REP(i, 1, n) max[i] = -INF;    for(int i = n; i > 0; i--)    {        int pos = std::lower_bound(max + 1, max + n + 1, a[i], std::greater<int>()) - max;        max[f[i] = pos] = a[i], LIS = std::max(pos, LIS);    }}void solve(){    read(m);    REP(i, 1, m)    {        read(L);        if(L > LIS)        {            puts("Impossible");            continue;        }        int last = -INF;        for(int i = 1; i <= n && L; i++)            if(L <= f[i] && a[i] > last)            {                   write(last = a[i]);                if(--L) putchar(' ');            }        puts("");       }}int main(){#ifndef ONLINE_JUDGE    freopen("1046.in","r",stdin);    freopen("1046.out","w",stdout);#endif    init(), prework(), solve();#ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;}
0 0
原创粉丝点击