zoukankan      html  css  js  c++  java
  • [HAOI 2007]上升序列

    Description

      对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax
    2 < … < axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。任务给
    出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先
    x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.

    Input

      第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M
    行每行一个数L,表示要询问长度为L的上升序列。N<=10000,M<=1000

    Output

      对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.

    Sample Input

    6
    3 4 1 2 3 6
    3
    6
    4
    5

    Sample Output

    Impossible
    1 2 3 6
    Impossible

    题解

    比较暴力...

    首先做一般的 $lis$ 都可以获得一个数组,如 $f_i$ 表示 $i$ 这个位置以前以 $a_i$ 结尾的最长上升子序列的长度。

    我们考虑反着做,记 $f_i$ 表示 $i$ 这个位置之后以 $a_i$ 开头的最长上升子序列的长度。

    然后处理询问 $len$ 的时候只需要从 $1$ 到 $n$ 扫一遍,记 $last$ 为上一个选出的数, $x$ 为待选序列长度。如果 $a_i > last$ 且 $f_i geq x$ ,便选上,将 $x-1$ 。

     1 //It is made by Awson on 2018.1.4
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <queue>
     7 #include <stack>
     8 #include <cstdio>
     9 #include <string>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define LD long double
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define Min(a, b) ((a) < (b) ? (a) : (b))
    19 using namespace std;
    20 const int N = 10000;
    21 const int INF = ~0u>>1;
    22 
    23 int n, m, a[N+5], f[N+5], w[N+5], x, maxlen;
    24 
    25 void print(int x) {
    26     int last = 0;
    27     for (int i = 1; i <= n; i++) {
    28     if (f[i] >= x && last < a[i] && x) {
    29         if (last != 0) printf(" ");
    30         last = a[i];
    31         printf("%d", a[i]);
    32         x--;
    33     }
    34     }
    35     printf("
    ");
    36 }
    37 int dev(int l, int r, int val) {
    38     int ans = 0;
    39     while (l <= r) {
    40     int mid = (l+r)>>1;
    41     if (w[mid] > val) l = mid+1, ans = mid;
    42     else r = mid-1;
    43     }
    44     return ans;
    45 }
    46 void work() {
    47     scanf("%d", &n); w[0] = INF;
    48     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    49     for (int i = n; i >= 1; i--) {
    50     int pos = dev(0, maxlen, a[i]); maxlen = Max(maxlen, pos+1);
    51     f[i] = pos+1;
    52     if (f[i] == maxlen) w[maxlen] = a[i];
    53     else w[f[i]] = Max(w[f[i]], a[i]);
    54     }
    55     scanf("%d", &m);
    56     while (m--) {
    57     scanf("%d", &x);
    58     if (x > maxlen) printf("Impossible
    ");
    59     else print(x);
    60     }
    61 }
    62 int main() {
    63     work();
    64     return 0;
    65 }
  • 相关阅读:
    20199301 2019-2020-2 《网络攻防实践》 第九周作业
    20199301 2019-2020-2 《网络攻防实践》第八周作业
    第六课 网络安全防范技术实践验收
    20199301 2019-2020-2 《网络攻防实践》 第六周作业
    20199301 2019-2020-2 《网络攻防实践》 第五周作业
    某次发言
    FATE安装部署日志
    期末大作业
    python爬虫
    20199302 2019-2020-2 《网络攻防实践》第12周作业
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8191760.html
Copyright © 2011-2022 走看看