down
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;
}
随机推荐
- leetcode-4-basic
解题思路:这道题比较简单,代码不贴了.需要注意的是: 数字与字符串之间的转换, char str[100]; sprintf(str, "%d", num); 解题思路: 这道题是 ...
- Three displays CodeForces - 987C (dp)
C. Three displays time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- MyBatis拦截器打印不带问号的完整sql语句方法
/* Preparing: SELECT * FROM tb_user WHERE id = ? AND user_name = ? 目标是打印:SELECT * FROM tb_user WHER ...
- matlab 初级画图
matlab 初级画图 1.plot() plot(x,y) plots each vector pairs (x,y) 画图函数画出每个点 每组变量 plot (y) plots eac ...
- tensorflow——MNIST机器学习入门
将这里的代码在项目中执行下载并安装数据集. 执行下面代码,训练.并评估模型: # _*_coding:utf-8_*_ import inputdata mnist = inputdata.read_ ...
- [python学习篇][廖雪峰][2][高级函数] map 和reduce
我们先看map.map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. 举例说明,比如我们有一个函数f(x)=x2,要把这个函数 ...
- [python篇] [伯乐在线][1]永远别写for循环
首先,让我们退一步看看在写一个for循环背后的直觉是什么: 1.遍历一个序列提取出一些信息 2.从当前的序列中生成另外的序列 3.写for循环已经是我的第二天性了,因为我是一个程序员 幸运的是,Pyt ...
- 浏览器提示ERR_CONTENT_DECODING_FAILED,Gzip压缩数据无法解压
最近在页面上有个显示数据表格的功能,数据由后台传给前台JS表格插件.数据格式为JSON 由于数据量很大,就想到用GZIP压缩以后传给前台.压缩前,某个表格的数据量达到3M多,用GZIP压缩后就200K ...
- 【Luogu】P3521ROT-Tree Rotations(线段树合并)
题目链接 神奇的线段树合并qwq 不过就思路而言很好想…… 观察到一棵树无论怎么交换两棵左右子树,子树内部的最优逆序对并没影响……决策只影响左右子树之间的逆序对…… 于是线段树合并直接乱搞就好啦 ...
- Codeforces 903E Swapping Characters
题目大意 考虑一个未知的长为 $n$($2\le n\le 5000$)由小写英文字母构成的字符串 $s$ .给出 $k$($1\le k\le 2500$,$nk\le 5000$)个字符串 $s_ ...