codeforces 447C. DZY Loves Sequences 解题报告(446A)

题目链接:http://codeforces.com/problemset/problem/447/C

题目意思:给出 一个 包含 n 个数的序列你,从中需要找出这个序列的最长子串,满足在里面只修改其中一个元素,使得这个子串的元素严格递增,求出这个长度是多少。

  以为是DP题(它的分类确实是DP题),无从下手。看了下别人写的,有些部分不太明白;根据自己的理解再结合一些别人的,加了些特判,总算过了^_^,我好像觉得我的做法不像是用了DP思想咯........

     总体思路就是:设两个数组,分别为inc_left[] 和 inc_right[],顾名思义,对于第 i 个元素,inc_left[i]就是从左到右扫描序列,到达这个inc_left[i]元素的时候,它的递增长度是多少。举个例子,对于test 1 中的   7  2  3   1  5   6

                  inc_left[i]为: 1  1  2   1   2   3

      对于6这个数来说,inc_left[6] = 3 是因为 1 5 6 严格递增。而为什么有些inc_left[i] = 1,是因为前面加上自己,不构成递增序列。inc_right[]依次类推。

      这两个数组结合起来就可以求出 2 3 1 5 6 的情况了,即对于某个a[i],只改变a[i]这个数,使得以这个a[i] 为原点,左右扩散起来,能够构成的最长递增序列。

      要注意一些特判,例如,当n  = 1 时直接输出1;如果输入序列本来已经严格递增,直接输出n。最后一种情况就是,1 1 这种,只改变其中一个元素,答案为2,代码中的

ans = max(ans, max(inc_left[i]+1, inc_right[i]+1));   就是为了应对这种情况的。

    

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int N = 1e5 + 5;
 8 int a[N], inc_left[N], inc_right[N];
 9 
10 int main()
11 {
12     int n;
13     while (scanf("%d", &n) != EOF)
14     {
15         memset(a, 0, sizeof(a));
16         for (int i = 1; i <= n; i++)
17             scanf("%d", &a[i]);
18         if (n == 1)
19             printf("1
");
20         else
21         {
22             int ans = 0;
23             inc_left[1] = 1;
24             for (int i = 2; i <= n; i++)
25             {
26                 inc_left[i] = (a[i] > a[i-1] ? inc_left[i-1]+1 : 1);
27                 ans = max(ans, inc_left[i]);
28             }
29             inc_right[n] = 1;
30             for (int i = n-1; i >= 1; i--)
31             {
32                 inc_right[i] = (a[i+1] > a[i] ? inc_right[i+1]+1 : 1);
33                 ans = max(ans, inc_right[i]);
34             }
35             if (ans == n)  // 处理序列本来就是递增情况
36                 printf("%d
", n);
37             else
38             {
39                 for (int i = 1; i <= n; i++)
40                 {
41                     if (a[i+1] > a[i-1]+1)    // 这两种情况需排除:1 ? 2 或 1 ? 1,可以更改的至少需要满足1 ? 3
42                         ans = max(ans, inc_right[i+1]+inc_left[i-1]+1);
43                     else
44                         ans = max(ans, max(inc_left[i]+1, inc_right[i]+1));  // 处理 1 1的情况,只能更改其中一个
45                 }
46                 printf("%d
", ans);
47             }
48         }
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/windysai/p/3843642.html