HDU 4513吉哥系列故事——完美队形II Manacher
作者:互联网
HDU 4513吉哥系列故事——完美队形II Manacher
题意
吉哥又想出了一个新的完美队形游戏!
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:
- 挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
- 左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
- 从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则
H[1] <= H[2] <= H[3] .... <= H[mid]
。
现在吉哥想知道:最多能选出多少人组成新的完美队形呢?
解题思路
看到这里序列的特殊要求实际上不就是个回文串嘛,那肯定就是Manacher
算法了。
关键是如何处理大小关系呢,这里是在模板中加了一些判断就可以解决:
- 中间插入的不再是字符,而是数字,这里我们插入
0x3f3f3f3f
这个来进行代替。 - 在判断完对称的数字相等之后还要判断是否小于,这里需要知道两个实际的数之间有我们插的数,这个需要注意。
- 其他细节看代码。
代码实现
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+7;
int num[maxn], tmp[maxn<<1];
int p[maxn<<1];
int t, n;
void init()
{
tmp[0]=inf+1;
for(int i=1; i<=2*n; i+=2)
{
tmp[i] = inf;
tmp[i+1] = num[i>>1];
}
tmp[(n<<1)+1]=inf;
tmp[(n<<1)+2]=inf+1;
}
int manacher(int *st, int len)
{
int mx=0, ans=0, po=0;
for(int i=1; i<=len; ++i)
{
if(mx > i)
p[i]=min( mx-i, p[ (po<<1) - i ] );
else
p[i]=1;
while(st[ i - p[i]] ==st[ i + p[i]] )
{
if( st[ i-p[i] ] == inf)
p[i]++;
else if(st[ i-p[i] ] <= st[ i-p[i]+2 ])
p[i]++;
else break;
}
if(p[i]+i>mx)
{
mx=p[i]+i;
po=i;
}
ans=max(ans, p[i]);
}
return ans-1;
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%d", &num[i]);
init();
// for(int i=1; i<=2*n+1; i++)
// printf("%d ", tmp[i]);
// printf("\n");
int ans=manacher(tmp, n*2+1);
printf("%d\n", ans);
}
return 0;
}
标签:HDU,int,4513,II,完美,maxn,Manacher,吉哥,队形 来源: https://www.cnblogs.com/alking1001/p/12248537.html