洛谷P1108 低價購買題解
阿新 • • 發佈:2018-07-01
序列 ns2 每一個 解決 價格 const mat 沒有 方程 ,同時還要去重\(c[i]-=\sum\limits_{1\leqslant j<i,a[i]=a[j],f[i]=f[j]}c[j]\)。
上代碼:
看到“你必須用低於你上次購買它的價格購買它”,有沒有想到什麽?沒錯,又是LIS,倒過來的LIS,所以我們只要把讀入的序列倒過來就可以求LIS了,第一問解決。
首先要厘清的是,對於這一題第二問貌似用\(nlog_{2}n\)的算法不是很好,因為我們需要序列中每一個位置可以接成LIS的長度。再看看數據範圍,會發現\(n^2\)完全可做。仔細想一想,不難發現第二問其實也是個\(DP\):若\(f[i]\)表示以\(i\)位置為結尾的LIS的長度,\(c[i]\)表示序列\(1\)~\(i\)位置按照最優選擇的方案數,則狀態轉移方程\(c[i]=\sum\limits_{1\leqslant j<i,a[i]>a[j],f[i]=f[j]+1}c[j]\)
上代碼:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5005;
int n, a[N], f[N], c[N], ans1, ans2;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[n+1-i];
for(int i = 1; i <= n; i++) { \\常規n^2解法
f[i] = 1;
for(int j = 1; j < i; j++)
if(a[i]>a[j]) f[i] = max(f[i], f[j]+1);
ans1 = max(ans1, f[i]);
}
for(int i = 1; i <= n; i++) {
if(f[i] == 1 ) c[i] = 1; \\初始化
for(int j = 1; j < i; j++) {
if(f[i] == f[j] && a[i] == a[j]) c[i] -= c[j]; \\去重
if(f[i] == f[j]+1 && a[i] > a[j]) c[i] += c[j]; \\狀態轉移
}
}
for(int i = 1; i <= n; i++)
if(f[i] == ans1) ans2 += c[i]; \\統計答案
cout << ans1 << " " << ans2;
return 0;
}
洛谷P1108 低價購買題解