题意:
爬山,前半段非递减,后半段非递增
灵魂画师
思路:
在manacher中mp改变条件加一个跳过原来的加入的值的条件以及加一个判断控制最中间向两边满足非递增条件。
Ac代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s[111000];
ll ma[222000];
ll mp[222000];
ll lh;
void manacher(ll len)
{
//先处理数组,处理出来的数组是ma
s[0]=s[len];
s[len+1]=s[1];
lh=2;
ma[1]=(s[0]+s[1])/2;//可以不用写成这种处理,可直接赋值为-2或其他不影响的值
ma[0]=-1;
for(ll i=1;i<=len;i++)
{
ma[lh++]=s[i];
ma[lh++]=(s[i]+s[i+1])/2;
}
//开始真正的马拉车咯
ll mx=0,id=0;
for(ll i=1;i<lh;i++)
{
mp[i]=mx>i?min(mp[2*id-i],mx-i):1;
//mx>i的话与i对称位的mp和mx-i取最小
while(ma[i+mp[i]]==ma[i-mp[i]]&&ma[i-mp[i]]<=ma[i-mp[i]+1])
//处理后的数组不断扩大,mp不断改变
//条件多了一个递增递减哈
mp[i]++;
if((i-mp[i])%2)
mp[i]++;
if(i+mp[i]>mx)//更新mx世之最大化
{
mx=mp[i]+i;
id=i;
}
}
}
int main()
{
ll t;
scanf("%lld",&t);
ll x;
while(t--)
{
scanf("%lld",&x);
for(ll i=1;i<=x;i++)
scanf("%d",&s[i]);
memset(mp,0,sizeof(mp));
memset(ma,0,sizeof(ma));
manacher(x);
ll ans=0;
for(ll i=1;i<=lh;i++)
{
if(ans<mp[i])
{
ans=mp[i]-1;
}
}
printf("%lld\n",ans);
}
return 0;
}