Loading [MathJax]/extensions/tex2jax.js

P1108:低价购买题解

主要思路

第一问还是很好答的,用\(O(n^2)\)的时间来完成求最长下降子序列的 DP。第二问我们可以设一个数组为\(g[]\)来储存方案数。转移方程可以很显然的得出为:

\[ g[i] = \sum_{j = 1}^{i-1} g[j], 当 f[i] = f[j] + 1 且 arr[i]<arr[j] \]

但是我们还需要去重,假设我们已经计算了之前转移过来的情况,那么我们要消去之前等效的状态,也就是消去第\(j\)项,满足\(f[j] == f[i] 且 arr[i] == arr[j]\)。下面是代码:

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// P1108.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 5050;
int n, arr[MAX_N], f[MAX_N], g[MAX_N], tot;
bool cmp(int a, int b) { return a > b; }
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &arr[i]);
for (int i = 1; i <= n; i++)
{
f[i] = 1;
for (int j = 1; j < i; j++)
if (arr[j] > arr[i])
f[i] = max(f[j] + 1, f[i]);
tot = max(tot, f[i]);
}
for (int i = 1; i <= n; i++)
{
if (f[i] == 1)
g[i] = 1;
for (int j = 1; j < i; j++)
{
if (f[i] == f[j] && arr[i] == arr[j])
g[j] = 0;
if (f[i] == f[j] + 1 && arr[j] > arr[i])
g[i] += g[j];
}
}
long long ans = 0;
for (int i = 1; i <= n; i++)
if (f[i] == tot)
ans += g[i];
printf("%d %lld", tot, ans);
return 0;
}
// P1108.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 5050; int n, arr[MAX_N], f[MAX_N], g[MAX_N], tot; bool cmp(int a, int b) { return a > b; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); for (int i = 1; i <= n; i++) { f[i] = 1; for (int j = 1; j < i; j++) if (arr[j] > arr[i]) f[i] = max(f[j] + 1, f[i]); tot = max(tot, f[i]); } for (int i = 1; i <= n; i++) { if (f[i] == 1) g[i] = 1; for (int j = 1; j < i; j++) { if (f[i] == f[j] && arr[i] == arr[j]) g[j] = 0; if (f[i] == f[j] + 1 && arr[j] > arr[i]) g[i] += g[j]; } } long long ans = 0; for (int i = 1; i <= n; i++) if (f[i] == tot) ans += g[i]; printf("%d %lld", tot, ans); return 0; }
// P1108.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 5050;
int n, arr[MAX_N], f[MAX_N], g[MAX_N], tot;
bool cmp(int a, int b) { return a > b; }
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &arr[i]);
    for (int i = 1; i <= n; i++)
    {
        f[i] = 1;
        for (int j = 1; j < i; j++)
            if (arr[j] > arr[i])
                f[i] = max(f[j] + 1, f[i]);
        tot = max(tot, f[i]);
    }
    for (int i = 1; i <= n; i++)
    {
        if (f[i] == 1)
            g[i] = 1;
        for (int j = 1; j < i; j++)
        {
            if (f[i] == f[j] && arr[i] == arr[j])
                g[j] = 0;
            if (f[i] == f[j] + 1 && arr[j] > arr[i])
                g[i] += g[j];
        }
    }
    long long ans = 0;
    for (int i = 1; i <= n; i++)
        if (f[i] == tot)
            ans += g[i];
    printf("%d %lld", tot, ans);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *