标签:ace 其他 min i++ 实现 连续 name 左右 cstring
吉哥又想出了一个新的完美队形游戏!
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:
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 4513吉哥系列故事——完美队形II Manacher
标签:ace 其他 min i++ 实现 连续 name 左右 cstring
原文地址:https://www.cnblogs.com/alking1001/p/12248537.html