Question: determine the length of the longest monotonic decreasing subsequence and the number of ways to reach the longest monotonic decreasing subsequence.
Idea: it is easier to find the longest monotonic decreasing subsequence. The key is to find the number of paths. In addition, deduplication is required. For example, 5 5 2 2 1 is actually only one 5 2 1. The difficulty lies in de-duplication. The de-duplication method is as follows:
We can use a double for loop to find the monotonic decreasing subsequence, in the loop, dp [I] indicates the longest length of the monotonic decreasing subsequence when the number of I is reached. We use the following for loop to find the length of the decreasing subsequence:
[Cpp]
For (int j = 0; j <I; ++ j ){
If (num [I] <num [j]) {
If (dp [j]> mmax)
Mmax = dp [j];
}
}
We set the array cnt [I] to indicate the maximum length of the number I in several ways. The value of cnt [I] is determined by cnt [j] (num [j]> num [I] and dp [j] = dp [I]-1 and j <I ), due to the need to go heavy, so it is difficult to think about it. I just got stuck here for a day .... You can use the following code:
[Cpp] view plaincopy
CLR (flag, false );
For (int j = I-1; j> = 0; -- j ){
If (num [I] <num [j]) {
If (dp [j] = mmax &&! Flag [num [j]) {
Flag [num [j] = true;
Cnt [I] + = cnt [j];
}
}
}
The flag array is the de-duplicated function, that is, if two identical numbers can reach num [I], one can be calculated and calculated from the back.
A few groups of data are attached:
5
20 18 25 18 17
Output: 3 2
4
20 15 10 10
Output: 3 1
9
100 96 30 200 196 30 300 296 30
Output: 3 3
5
5 5 2 2 1
Output: 3 1 www.2cto.com
If you have considered these situations, it is basically the right one.
Code:
[Cpp]
# Include <iostream>
# Include <string. h>
# Include <cstdio>
Using namespace std;
# Define CLR (arr, val) memset (arr, val, sizeof (arr ))
Const int n= 5010;
Int dp [N], num [N], sum [N];
Bool flag [10 * N];
Long cnt [N];
Int main (){
// Freopen ("1.txt"," r ", stdin );
Int n;
While (scanf ("% d", & n )! = EOF ){
For (int I = 0; I <n; ++ I)
Scanf ("% d", & num [I]);
CLR (dp, 0 );
CLR (cnt, 0 );
CLR (flag, false );
Dp [0] = 1; cnt [0] = 1;
Int mmax = 0;
For (int I = 1; I <n; ++ I ){
Mmax = 0;
For (int j = 0; j <I; ++ j ){
If (num [I] <num [j]) {
If (dp [j]> mmax)
Mmax = dp [j];
}
}
CLR (flag, false );
For (int j = I-1; j> = 0; -- j ){
If (num [I] <num [j]) {
If (dp [j] = mmax &&! Flag [num [j]) {
Flag [num [j] = true;
Cnt [I] + = cnt [j];
}
}
}
If (cnt [I] = 0) cnt [I] = 1;
Dp [I] = mmax + 1;
}
Mmax = 0;
For (int I = 0; I <n; ++ I ){
If (mmax <dp [I])
Mmax = dp [I];
}
Long ans = 0;
CLR (flag, false );
For (int I = n-1; I> = 0; -- I ){
If (dp [I] = mmax ){
If (! Flag [num [I]) {
Ans + = cnt [I];
Flag [num [I] = true;
}
}
}
Printf ("% d % lld \ n", mmax, ans );
}
Return 0;
}
This question has been stuck for more than a day ,,
10417832 ac_Bool 1952 Wrong Answer C ++ 739B 19:30:37
10429494 ac_Bool 1952 Accepted 296 K 125 ms c ++ 1215B 08:53:09 wa 8 times ....
Author: wmn_wmn