吉哥系列故事——完美队形II(马拉车算法)

Posted 哟吼!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了吉哥系列故事——完美队形II(马拉车算法)相关的知识,希望对你有一定的参考价值。

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

题意:

就是让你找到一个最长回文子串,如果这个串是偶数,那么他的左边一半就要满足i<j且Ai<=Aj,也就是非严格递增类型

如果是奇数,那么中间那个数大小可以不受限制

 

题解:

就是在马拉车算法里面加一个判断,只是我前边那一种写的太麻烦了,所以超时了

 

具体看代码:

技术图片
  1 //#include<stdio.h>
  2 //#include<string.h>
  3 //#include<iostream>
  4 //#include<algorithm>
  5 //#include<set>
  6 //using namespace std;
  7 //const int maxn=300005;
  8 //const int INF=0x3f3f3f3f;
  9 //const int mod=998244353;
 10 //int str[maxn],s[maxn];
 11 //int len,Len[maxn];
 12 //void init()
 13 //{
 14 //    memset(str,0,sizeof(str));
 15 //    int k=0;
 16 //    str[k++]=10000;
 17 //    for(int i=0;i<len;++i)
 18 //        str[k++]=1000,str[k++]=s[i];
 19 //    str[k++]=1000;
 20 //    len=k;
 21 //}
 22 //int manacher()
 23 //{
 24 //    Len[0]=0;
 25 //    int sum=0;
 26 //    int mx=0,id;
 27 //    for(int i=1;i<len;++i)
 28 //    {
 29 //        if(i<mx) Len[i]=min(mx-i,Len[2*id-i]);
 30 //        else Len[i]=1;
 31 //        while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++;
 32 //        if(Len[i]+i>mx)
 33 //        {
 34 //            mx=Len[i]+i;
 35 //            id=i;
 36 //            int flag=0;
 37 //            if((Len[i]-1)%2)
 38 //            {
 39 //                if(Len[i]-1>=5)
 40 //                for(int j=i-4;j>j-Len[i];j-=2)
 41 //                {
 42 //                    if(str[j]>str[j+2])
 43 //                    {
 44 //                        flag=1;
 45 //                        break;
 46 //                    }
 47 //                }
 48 //            }
 49 //            else
 50 //            {
 51 //                if(Len[i]-1>=4)
 52 //                for(int j=i-3;j>j-Len[i];j-=2)
 53 //                {
 54 //                    if(str[j]>str[j+2])
 55 //                    {
 56 //                        flag=1;
 57 //                        break;
 58 //                    }
 59 //                }
 60 //            }
 61 //            if(!flag)
 62 //            sum=max(sum,Len[i]);
 63 //        }
 64 //    }
 65 //    return sum-1;
 66 //}
 67 //int main()
 68 //{
 69 //    int t;
 70 //    scanf("%d",&t);
 71 //    while(t--)
 72 //    {
 73 //        memset(s,0,sizeof(s));
 74 //        scanf("%d",&len);
 75 //        for(int i=0;i<len;++i)
 76 //            scanf("%d",&s[i]);
 77 //        init();
 78 //        printf("%d\n",manacher());
 79 //    }
 80 //    return 0;
 81 //}
 82 #include<stdio.h>
 83 #include<string.h>
 84 #include<iostream>
 85 #include<algorithm>
 86 #include<set>
 87 using namespace std;
 88 const int maxn=300005;
 89 const int INF=0x3f3f3f3f;
 90 const int mod=998244353;
 91 int str[maxn],s[maxn];
 92 int len,Len[maxn];
 93 void init()
 94 {
 95     memset(str,0,sizeof(str));
 96     int k=0;
 97     str[k++]=-1;
 98     for(int i=0;i<len;++i)
 99         str[k++]=0,str[k++]=s[i];
100     str[k++]=0;
101     len=k;
102 }
103 void manacher()
104 {
105     Len[0]=0;
106     int sum=0;
107     int id,mx=0;
108     for(int i=1;i<len;++i)
109     {
110         if(i<mx)  Len[i]=min(mx-i,Len[2*id-i]);
111         else Len[i]=1;
112         int Min;
113         if(str[i] > 0) Min = str[i];
114         else Min = str[i + 1];
115         while(str[i - Len[i]] == str[i + Len[i]] && str[i - Len[i]] <= Min) {
116             //printf("are you here?\n");
117             if(str[i - Len[i]] > 0)
118                 Min = str[i - Len[i]];
119             if(i + Len[i] > mx) {
120                 mx = i + Len[i];
121                 id = i;
122             }
123             Len[i]++;
124         }
125     }
126     int ans = 0;
127     for(int i = 1; i < len; i++) ans = max(ans, Len[i]);
128     printf("%d\n", ans - 1);
129 }
130 //        if(Len[i]+i>mx)
131 //        {
132 //            mx=Len[i]+i;
133 //            id=i;
134 //            int flag=0;
135 //            if((Len[i]-1)%2)
136 //            {
137 //                if(Len[i]-1>=5)
138 //                for(int j=i-4;j>j-Len[i];j-=2)
139 //                {
140 //                    if(str[j]>str[j+2])
141 //                    {
142 //                        flag=1;
143 //                        break;
144 //                    }
145 //                }
146 //            }
147 //            else
148 //            {
149 //                if(Len[i]-1>=4)
150 //                for(int j=i-3;j>i-Len[i];j-=2)
151 //                {
152 //                    if(str[j]>str[j+2])
153 //                    {
154 //                        flag=1;
155 //                        break;
156 //                    }
157 //                }
158 //            }
159 //            if(!flag)
160 //            sum=max(sum,Len[i]);
161 //        }
162 //    }
163 //    return (sum-1);
164 //}
165 int main()
166 {
167     int t;
168     scanf("%d",&t);
169     while(t--)
170     {
171         scanf("%d",&len);
172         for(int i=0;i<len;++i)
173             scanf("%d",&s[i]);
174         init();
175         manacher();
176         //printf("%d\n",);
177     }
178     return 0;
179 }
View Code

 

以上是关于吉哥系列故事——完美队形II(马拉车算法)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4513 吉哥系列故事——完美队形II (manachar算法)

HDU 4513 吉哥系列故事——完美队形II (Manacher变形)

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

HDU 4513 吉哥系列故事――完美队形II(Manacher)

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

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