UVa 10534 - Wavio Sequence

传送门

UVa 10534 - Wavio Sequence

题意

从给定的序列中找出一个波浪序列,使前n + 1个数严格递增,后n + 1个数严格递减

思路

从两边分别找出以每个位置结束的最长递增序列,然后取他们两边的最小值。因为长度必须要相等,但是可以牺牲长的。
一开始用$O(n^2)$的dp,TLE了。参考了shuangde800 的解题报告才了解还有一种$O(nlogn)$的方法。学习之。

代码

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 10000 + 100;
 
int num[MAXN], left[MAXN], right[MAXN];
vector<int> ve;
 
int main()
{
    //freopen("in.txt", "r", stdin);
    int T, i, j, n;
    while (~scanf("%d", &n))
    {
        for (i = 0; i < n; i++)
            scanf("%d", #[i]);
        ve.clear();
        for (i = 0; i < n; i++)
        {
            if (ve.empty() || num[i] > ve.back())
                ve.push_back(num[i]);
            else
            {
                int t = lower_bound(ve.begin(), ve.end(), num[i]) - ve.begin();
                ve[t] = num[i];
            }
            left[i] = ve.size();
        }
        ve.clear();
        for (i = n - 1; i >= 0; i--)
        {
            if (ve.empty() || num[i] > ve.back())
                ve.push_back(num[i]);
            else
            {
                int t = lower_bound(ve.begin(), ve.end(), num[i]) - ve.begin();
                ve[t] = num[i];
            }
            right[i] = ve.size();
        }
        int ans = 0;
        for (i = 0; i < n; i++)
            ans = max(ans, min(left[i], right[i]) * 2 - 1);
        printf("%d\n", ans);
    }
    return 0;
}

Powered by Jekyll and Theme by solid