• CodeForces 446A. DZY Loves Sequences(最长上升子序列)


    题意:给定一个长度为n的序列,可以修改任何一个字符,求修改后最长的单调严格上升子序列(必须是连续的)。

    分析:((1 <= n < 10^5)),数据范围很大,不能使用(o(n^2))的算法。所以我们可以从线性角度考虑,一种常见的套路是枚举修改点,然后求最大值。我们只需要分别求出两端的情况即可,从开头到结尾的以第i个数结尾的最长上升子序列,和从结尾到开头的以第i个数开头的最长上升子序列。然后枚举修改点,只要(a[i + 1] - a[i] >= 2),那么这两个最长的子序列就可以连接起来,更新答案。

    注意除了这种情况,我们还可以不连接起来,这种情况一定不要忘记,这样也可以更新答案。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 100005;
    LL a[N];
    int f[N];
    int f2[N];
    int main()
    {
    	int n;
    	scanf("%d", &n);
    
    	for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    
    	if (n == 1)
    	{
    		puts("1");
    	}
    	else if (n == 2)
    	{
    		puts("2");
    	}
    	else
    	{
    		f[1] = 1;
    		for (int i = 2; i <= n; ++i)
    		{
    			f[i] = 1;
    			if (a[i] > a[i - 1]) f[i] = f[i - 1] + 1;
    		}
    
    		f2[n] = 1;
    		for (int i = n - 1; i >= 1; --i)
    		{
    			f2[i] = 1;
    			if (a[i] < a[i + 1]) f2[i] = f2[i + 1] + 1;
    		}
    
    		int res = 0;
    		//修改一个
    		for (int i = 1; i <= n - 1; ++i)
    		{
    			if (a[i] >= a[i + 1]) res = max(res, f[i] + 1);
    		}
    
    		for (int i = n - 1; i >= 1; --i)
    		{
    			if (a[i] >= a[i + 1]) res = max(res, f2[i + 1] + 1);
    		}
    
    		for (int i = 2; i <= n - 1; ++i)
    		{
    			if (a[i + 1] - a[i - 1] >= 2) res = max(res, f2[i + 1] + f[i - 1] + 1);
    		}
    
    
    		printf("%d
    ", res);
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    gems gems gems
    poj 6206 Apple
    lightoj1341唯一分解定理
    lightoj1370欧拉函数
    约瑟夫环lightoj1179
    拓展欧几里得算法
    RMQ算法
    poj1502MPI Maelstrom
    poj1860Currency Exchange
    生成全排列
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13307113.html
Copyright © 2020-2023  润新知