• 吉哥系列故事——完美队形II(Manacher)


      吉哥又想出了一个新的完美队形游戏!
      假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] … h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:

    1、挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
    2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
    3、从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] … <= H[mid]。

    现在吉哥想知道:最多能选出多少人组成新的完美队形呢?

    Input
      输入数据第一行包含一个整数T,表示总共有T组测试数据(T <= 20);
      每组数据首先是一个整数n(1 <= n <= 100000),表示原先队形的人数,接下来一行输入n个整数,表示原队形从左到右站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。
      
    Output
      请输出能组成完美队形的最多人数,每组输出占一行。
      
    Sample Input
    2
    3
    51 52 51
    4
    51 52 52 51

    Sample Output
    3
    4

    题意:
    最长回文串+先增

    思路:
    最长回文串,用马拉车

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 using namespace std;
     5 
     6 int b[200005];
     7 int len[200005];
     8 
     9 int manacher(int n)
    10 {
    11     int id, re, maxx, i;
    12     re = 0;
    13     maxx = 0;
    14     for(i = 1; i < n; i++)
    15     {
    16         if(maxx > i) len[i] = min(len[2*id-i], maxx-i);
    17         else len[i] = 1;
    18         while(b[i-len[i]] == b[i+len[i]]&&(b[i-len[i]]==0||b[i-len[i]]<=b[i-len[i]+2]))
    19         {
    20             len[i]++;
    21         }
    22         if(maxx < len[i] + i)
    23         {
    24             id = i;
    25             maxx = len[i] + i;
    26         }
    27         re = max(re, len[i]-1);
    28     }
    29     return re;
    30 }
    31 
    32 int main()
    33 {
    34     int t, n, i, j, re;
    35     int a[100005];
    36     scanf("%d", &t);
    37     while(t--)
    38     {
    39         scanf("%d", &n);
    40         for(i=0;i<n;i++)
    41         {
    42             scanf("%d", &a[i]);
    43         }
    44         memset(len, 0, sizeof(len));
    45         b[0] = -1;
    46         b[1] = 0;
    47         j = 2;
    48         for(i=0;i<n;i++)
    49         {
    50             b[j++] = a[i];
    51             b[j++] = 0;
    52         }
    53         n = j;
    54         re = manacher(n);
    55         printf("%d
    ", re);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    腾讯本月将出QQ for Linux!
    OpenSolaris 初体验
    OpenSolaris 初体验
    简易背单词
    NetBeans 全球翻译团队Tshirt发放~
    上传图片时预览效果
    使用ATL开发ActiveX控件
    Visual Studio 2010 Visual C++ 确定要重新分发的 DLL
    动态链接导入库与静态链接库
    20110413 15:54 利用事件触发实现ActiveX调用js函数
  • 原文地址:https://www.cnblogs.com/0xiaoyu/p/11298136.html
Copyright © 2020-2023  润新知