• JZOJ 4227. 【五校联考3day2】B


    题目

    Description

    小D是雅礼高一著名的神犇,在NOI同步赛中获得了满分的优异成绩,而全国没有任何其他人获得如此的成绩。
    某天晚上,高一内部在讨论一道题目,然而包括小D之内的各种神犇都毫无头绪,这时候,高二的人赢小T上来给高二进行了精彩的讲解。
    小D被小T的神犇气场所折服,他知道小T之所以没有同步赛满分是不屑于,于是他决定拜小T为师。
    一日小T正在给小D讲解后缀数组。
    “把一个字符串的所有非空后缀按字典序从小到大排序,然后按顺序排列出后缀的第一个字符在原串中的位置所形成的数组,就是后缀数组。如“ababa”的后缀数组就是{5, 3, 1, 4, 2}。”
    这里的位置从1开始编号,字符串仅包含小写英文字母。
    接着小T给小D讲解了它的构造过程。
    小D毕竟身为同步赛满分,水平还是不低,他立即举一反三:既然我们能给定一个字符串,给出他的后缀数组,那么给定后缀数组,能不能恢复字符串呢。
    小T说:“这是不行的,这个问题我几年前研究过,譬如说,假设你后缀数组是{2, 1},那么原串既可以是“aa”,也可以是“ bb”。然而,我们的确可以提出一些有趣的问题,我记得我小学的时候,研究过一个问题,给定一个长度为n的数组A,以及一个n × 26 的矩阵w,所有下标都从1开始,其中w_{i, j}表示第i个位置填第j个小写字母的价值,现在你需要给出一个长度为n的字符串,使得它的后缀数组是A,而且它每个位置的价值和最大。}这个问题可不简单,我小学的时候研究了整整一节课。”
    小D想了想,觉得自己大概就算在小学也只要一节课就想得出来。各位做题人你们会做吗?
     

    Input

    为了减少输入量,部分数据将在程序内生成。
    有一个随机数产生器,有个内部变量x初始时为x_0,每次产生随机数时它会将x变为(100000005x + 1532777326) mod 998244353,然后返回x/100取下整。(a mod b 表示a除以 b的余数,该运算的优先级高于加减法。)
    输入一行两个两个整数n, x_0。
    首先输入一个1到n的排列,表示数组A,A的定义如题所述。
    接着你将按照先i递增,再j递增的顺序生成w_{i, j}。每次生成一个随机数r,则w_{i, j} = r mod {10^4}。

    Output

    为了减少输出量,你只需要输出最大的价值和,不需要给出对应的字符串。
    输出一行一个整数表示最大的价值和。
     

    Sample Input

    输入1:
    1 493941464
    1
    输入2:
    2 736594838
    1 2
    输入3:
    5 910387714
    1 2 3 4 5
    输入4:
    15 892431401
    8 5 9 1 2 7 11 3 14 15 13 10 12 6 4

    Sample Output

    输出1:
    9490
    样例1解释:
    答案即为权值最大的字母的权值,计算得f的权值为9490最大。前六个字母的权值依次为5602, 7113, 5633, 756, 8496, 9490。
    输出2:
    16658
    样例2解释:
    计算得“sw”的权值为16658最大,注意虽然“wf” 的权值是17957,但是它的后缀数组为{2, 1},不满足条件;“ww”的权值为16935,但由于“w” 的字典序小于“ww” 所以后缀数组也是{2, 1}。
    输出3:
    44455
    样例3解释:
    对应的字符串为“hoooq”。
    输出4:
    129724
     

    Data Constraint

    对于前20%的数据,n ≤ 5。
    对于前40%的数据,n ≤ 15。
    对于前60%的数据,n ≤ 1000。
    对于前100%的数据,n ≤ 100000,0 ≤ x_0 ≤ 998244353。保证存在一个仅含小写英文字母的字符串,使得它的后缀数组为A。

     

    大意

    把一个字符串的所有非空后缀按字典序从小到大排序,然后按顺序排列出后缀的第一个字符在原串中的位置所形成的数组,就是后缀数组。如“ababa”的后缀数组就是{5, 3, 1, 4, 2}。

    给定一个长度为n的数组A,以及一个n × 26 的矩阵w,所有下标都从1开始,其中w_{i, j}表示第i个位置填第j个小写字母的价值,现在你需要给出一个长度为n的字符串,使得它的后缀数组是A,而且它每个位置的价值和最大。

    分析

    每个字母对应后缀数组的一段区间

    考虑一下后缀数组中每个下标的后继在后缀数组中的位置,形成一个新的数组,那么每个字母对应的区间中这个数组的元素一定是单调递增的

    然后直接设f[i][j]表示到了后缀数组中的第i个位置,填到了第j个字母的最大价值

    n==1     特别处理一下

     

    代码

     1 #include<iostream>
     2 #define N 100010
     3 using namespace std;
     4 int n,seed,w[N][30],a[N],z[N],rank[N],f[N][30],ans;
     5 int rand()
     6 {
     7     seed=(long long)(100000005ll*(long long)seed+1532777326ll)%998244353ll;
     8     return seed/100;
     9 }
    10 int main ()
    11 {
    12     ios::sync_with_stdio(false);
    13     cin>>n>>seed;
    14     for (int i=1;i<=n;i++)
    15       for (int j=0;j<26;j++)
    16           w[i][j]=rand()%10000;
    17     for (int i=1;i<=n;i++)
    18         cin>>a[i],rank[a[i]]=i;
    19     for (int i=0;i<26;i++)
    20     {
    21         f[1][i]=w[a[1]][i];
    22         if (n==1) ans=max(ans,f[1][i]);
    23     }
    24     for (int i=2;i<=n;i++)
    25     {
    26         for (int j=0;j<26;j++)
    27         {
    28             for (int k=0;k<=j;k++)
    29             {
    30                 if (k==j&&rank[a[i]+1]<=rank[a[i-1]+1]) continue;
    31                    f[i][j]=max(f[i][j],f[i-1][k]+w[a[i]][j]);
    32             }
    33             if(i==n) ans=max(ans,f[i][j]);
    34         }
    35     }
    36     cout<<ans;
    37 }

     

     

    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    vs与linux的交叉编译环境搭建
    layui框架部分功能介绍
    谷歌添加百度翻译提示Google已将百度翻译标记为恶意程序并阻止安装,怎么办
    七,JOBC数据库编程
    mysql数据库
    六,IO系统
    五,图形界面编程
    四,集合框架
    三,反射类
    二,常用类
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/10331977.html
Copyright © 2020-2023  润新知