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


    吉哥系列故事——完美队形II

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 5889    Accepted Submission(s): 2375

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4513

    Description:

    吉哥又想出了一个新的完美队形游戏!
    假设有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

    题解:

    这个也是找最长回文子串但是有一些限制,其实就是稍微将Manacher算法变一下,加上这些限制就好了~

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N = 200005;
    int t;
    int a[N],b[N],p[N];
    int n;
    void solve(){
        int mx=0,id=0;
        memcpy(b,a,sizeof(a));
        a[0]=-1;
        for(int i=1;i<=2*n+1;i++){
            if(i&1) a[i]=0;
            else a[i]=b[i/2];
        }
        //for(int i=1;i<=2*n;i++) cout<<a[i]<<" ";
        //cout<<endl;
        for(int i=2;i<=2*n;i++){
            if(i>=mx) p[i]=1;
            else p[i]=min(mx-i,p[2*id-i]);
            //if(i<mx) continue ;
            while(i-p[i]>=0&&a[i-p[i]]==a[i+p[i]] && ((a[i-p[i]]<=a[i-p[i]+2]&&a[i+p[i]]<=a[i+p[i]-2])||a[i-p[i]]==0)) p[i]++;
            if(p[i]+i>mx){
                mx=p[i]+i;
                id=i;
            }
        }
    }
    int main(){
        cin>>t;
        while(t--){
            scanf("%d",&n);
            memset(p,0,sizeof(p));
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            solve();
            int ans = 1;
            for(int i=1;i<=2*n;i++){
                ans=max(ans,p[i]-1);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    unity中制作模拟第一人称视角下的指南针
    unity3D 中的C#脚本一个类调用另一类中简单方法
    unity中UI的屏幕自适应代码
    unity中导入插件时报错处理办法
    Unity3D在C#编程中的一些命名空间的引用及说明
    Unity中物体碰撞后去掉相互之间的反弹力
    unity3D打包发布Apk详细步骤
    unity3D开发的程序发布到Android平台上进行运行测试的详细步骤
    JAVA的环境变量配置(方式二)
    Java中的 JDK下载和环境配置(方式一)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10479811.html
Copyright © 2020-2023  润新知