# 題目: UVa 10534 - Wavio Sequence
# 題目說明
給一個長度為 n
的整數序列,求此序列的 LIS
與 LDS
相連最長為多少
LIS
的結尾與 LDS
的開頭為同一個字LIS
的長度與 LDS
相同
INPUT:
每筆測資輸入一個整數 n
,代表序列長度
接下來輸入 n
個整數
OUTPUT:
輸出相同長度且相連的最大 LIS
與 LDS
的合
# 解題方法
若使用普通 DP
的方式找 LIS
與 LDS
會超時,所以使用 greedy algorithm
加速
分別找出 LIS
與 LDS
與每個元素的位置
( LDS
的找法為反向做 LIS
)
之後設一個 t
從 LIS
與 LDS
中比較小的開始尋找
若 LIS
與 LDS
中的元素位置 num1[i]
與 num2[i]
皆不小於 t
,則跳出
輸出答案為 t * 2 - 1
更詳細關於 LIS
與 LDS
每個元素的位置
可以參考這篇
# 參考程式碼
#include <iostream> | |
#include <vector> | |
using namespace std; | |
int main() | |
{ | |
int n; | |
while (cin >> n) | |
{ | |
vector<int> str(n); | |
for (int i = 0; i < n; ++i) cin >> str[i]; | |
vector<int> lis; | |
vector<int> lds; | |
lis.emplace_back(str[0]); | |
lds.emplace_back(str[n - 1]); | |
vector<int> num1(n); | |
vector<int> num2(n); | |
num1[0] = 1; | |
num2[n - 1] = 1; | |
int cnt1 = 1; | |
int cnt2 = 1; | |
for (int i = 1; i < n; ++i) | |
{ | |
//lis | |
if (str[i] > lis.back()) | |
{ | |
lis.emplace_back(str[i]); | |
num1[i] = ++cnt1; | |
} | |
else | |
{ | |
auto it = lower_bound(lis.begin(), lis.end(), str[i]); | |
*it = str[i]; | |
num1[i] = (it - lis.begin() + 1); | |
} | |
//lds | |
int j = n - i - 1; | |
if (str[j] > lds.back()) | |
{ | |
lds.emplace_back(str[j]); | |
num2[j] = ++cnt2; | |
} | |
else | |
{ | |
auto it = lower_bound(lds.begin(), lds.end(), str[j]); | |
*it = str[j]; | |
num2[j] = (it - lds.begin() + 1); | |
} | |
} | |
int t = min(cnt1, cnt2); | |
for (; t > 0; --t) for (int i = 0; i < n; ++i) | |
if (num1[i] >= t && num2[i] >= t) goto out; | |
out: | |
cout << t * 2 - 1 << "\n"; | |
} | |
} |