• B


    【题目描述】

    给定k,你需要找到一个最小的n,使得有至少一个1~n的排列不是任何一个字符集不超过k的字符串的后缀排名数组,并构造出这样的排列中字典序最小的一个。

    后缀排名数组指:对于一个字符串,将其所有后缀按字典序排序,第i的后缀排名为a[i]。如abbab的后缀排名数组为 2 5 4 1 3。

    【输入】

    一行一个正整数k。

    【输出】

    输出包含两行。第一行为n,第二行为一个1~n的排列满足题目条件。

    【输入样例】

    2

    【输出样例】

    3
    2 1 3

    【提示】

    长为2的字符集不超过2的字符串有aa,ab,ba。后缀排名数组分别为2 1,1 2,2 1。包含了所有的排列。长为3的字符集不超过2的字符串有aaa,aab,aba,abb,baa,bab,bba。后缀排名数组分别为3 2 1,1 2 3,2 3 1,1 3 2,3 2 1,3 1 2,3 2 1。因此2 1 3是符合条件的解。

    对于20%的数据点,1<=k<=10;

    对于50%的数据点,1<=k<=1000;

    对于100%的数据点,1<=k<=100000。

    发现当n <= k的时候一定存在合法序列,考虑n = k + 1

    我们要使每个位置的字母都不相同,这样即不合法。

    即对于位置 a 和 b,a + 1 和 b + 1 与 a 和 b 之间的大小关系应该相反。

    否则就可以令 a 和 b 为同一字符。

    然后考虑n,显然任何数都比它小,所以它后面应该是最小的:0,所以放最后。

    考虑1,显然任何数都比它大,所以它后面应该是最大的:n

    然后交替倒推即可构造。

     1 #include <cstdio>
     2 const int N = 100010;
     3 
     4 int a[N];
     5 
     6 int main() {
     7     int n;
     8     scanf("%d", &n);
     9     n++;
    10     printf("%d
    ", n);
    11     int t = n + 1;
    12     for(int i = n; i > 0; i -= 2) {
    13         a[i] = --t;
    14     }
    15     for(int i = a[1] ? 2 : 1; i <= n; i += 2) {
    16         a[i] = --t;
    17     }
    18     for(int i = 1; i <= n; i++) {
    19         printf("%d ", a[i]);
    20     }
    21     return 0;
    22 }
    AC代码

    关于字典序最小,据说可以证明这样构造出来的是 n = k + 1 时的唯一解。不会。

  • 相关阅读:
    WebStorm使用Vue
    hive的简单操作
    hbase的简单操作
    CentOS 7 配置hadoop(五) 配置sqoop(伪分布)
    CentOS7配置hadoop集群
    CentOS 7 配置hadoop(四) 配置hive(伪分布)
    CentOS 7 配置hadoop(三) 配置hbase(伪分布)
    五种变量创建的方法
    GO练习题
    第一次作业总结
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9396441.html
Copyright © 2020-2023  润新知