Description

给出一个数列,求出这个序列的最长下降子序列的长度及方案数,子序列中的权值完全相同视为同一个序列

Input

第一行一个整数n,接下来一行n个整数表示序列的权值

Output

一行两个整数分别表示最长的长度及方案数

Sample Input

样例输入1:

12

68 69 54 64 68 64 70 67 78 62 98 87

样例输入2:

3

3 2 2

样例输出1:

4 2

样例输出2:

2 1

HINT

数据范围:

对于20%的数据n <= 10

对于50%的数据n <= 200

对于100%的数据n<= 5000,权值<= 100000,答案不会超出int64(pascal),long long(c++)范围


要求出最长下降子序列长度及方案数是非常容易的. 关键在于去重.

对于去重, 可以从头到尾再DP一次.

第一次DP得到f[i], 即以i为结尾的子串的个数.

第二次DP维护cnt[i], 表示以i为结尾的长度为f[i]的不同子串的个数.

具体维护方法是, j从前往后扫, 至i的位置. 假若有 f[j] == f[i] - 1 且 满足a[j] > a[i], 则将j统计入i的前一位中, 即 cnt[i] += cnt[j]. 对于f[i] == 1的位置, cnt[i]直接赋值为1, 表示有且仅有一种情况, 即为它本身. 至于去重, 假如有 a[j] == a[i] 且 j < i, 则将cnt[j]直接赋值为0, 表示以j为结尾的情况在i中都已经进行累加, 以避免后面重复计算.

这题当时不会写, 只拿了暴力分20, 真的很不应该.

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxN = (int)5e5;
int a[maxN];
int f[maxN];
long long cnt[maxN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("down.in", "r", stdin);
freopen("down.out", "w", stdout);
#endif
int n;
cin >> n;
for(int i = 0; i < n; i ++)
cin >> a[i];
memset(f, 0, sizeof(f));
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < i; j ++)
if(a[j] > a[i])
f[i] = max(f[j] + 1, f[i]);
if(! f[i])
f[i] = 1;
}
for(int i = 0; i < n; i ++)
{
if(f[i] == 1)
cnt[i] = 1;
for(int j = 0; j < i; j ++)
if(a[j] > a[i] && f[j] == f[i] - 1)
cnt[i] += cnt[j];
for(int j = 0; j < i; j ++)
if(f[j] == f[i] && a[j] == a[i])
cnt[j] = 0;
}
long long maxLen = 0, ans = 0;
for(int i = 0; i < n; i ++)
{
if(f[i] > maxLen)
maxLen = f[i], ans = cnt[i];
else if (f[i] == maxLen)
ans += cnt[i];
}
cout << maxLen << ' ' << ans << endl;
}

随机推荐

  1. ACM 贪心算法总结

    贪心算法的本质: 就是当前状态的最优解,它并不考虑全局. 什么是当前状态的最优解? 成本问题? https://www.cnblogs.com/xuxiaojin/p/9400892.html (po ...

  2. filter 作用

     过滤器 filter用于拦截用户请求,在服务器作出响应前,可以在拦截后修改request和response,这样实现很多开发者想得到的功能. filter是一个可以复用的代码片段,可以用来转换HTT ...

  3. Markdown 使用锚点

    首先是建立一个跳转的连接: [说明文字](#jump) 然后标记要跳转到什么位置即可: <span id = "jump">跳转到这里:</span>

  4. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] C】Greedy Arkady

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举那个人收到了几次糖i. 最好的情况显然是其他人都只收到i-1次糖. 然后这个人刚好多收了一次糖 也即 (i-1)kx + x & ...

  5. HSL颜色处理

    H--色调 S--饱和度 L--亮度 HSB(HSL) 色调饱和度亮度模式 以另外一种不同的理念进行色彩的调配 H色调 0~360 圆环形式 以角度表示 S 饱和度 0~1 之间的小数 L 亮度 0~ ...

  6. MySQL基本命令和常用数据库对象

    MySQL基本命令: 连接远程主机的MySQL服务(为了保证安全性,执行下面命令时,可以省略-p后面的密码,执行命令后系统会提示输入密码) mysql -p 密码 -u 用户名 -h 主机地址 --d ...

  7. sysctl内核参数解析

    sysctl内核参数解析 kernel.参数 kernel.shmall = 2097152    ## 1> 表示所有内存大小.可以分配的所有共享内存段的总和最大值.(以页为单位) ## 2& ...

  8. Linux下安装Mysql出现的常见问题以及解决办法

     1.安装时候出现 warning: mysql-community-server-5.7.13-1.el6.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ...

  9. iOS开发笔记--UILabel的相关属性设置

    在iOS编程中UILabel是一个常用的控件,下面分享一下UILabel的相关属性设置的方法. 很多学习iOS6编程都是从storyboard开始,用到UILabel时是将控件拖到storyboard ...

  10. 常用的Java基本代码汇总

    1.字符串和整型的相互转换 String a= String.valueOf(2); int i = Integer.parseInt(a); 2. 向文件末尾添加内容 BufferedWriter ...