Problem 1061: 好序列
Time Limits: 1000 MS Memory Limits: 65536 KB
64-bit interger IO format: %lld Java class name: Main
Description
楊神覺得好的序列需要符合這兩個條件
1.這段序列可以平均分成三段,第一段和第三段相同
2.第二段與第一段相反
給你一個由n個非負整數組成的序列,問連續子序列是好序列時,該連續子序列的長度是多少。
Input
第一行爲t 代表t組測試數據
第二行爲n ( 1 <= n <= 100000)代表序列由n個非負整數組成
第三行爲n個數 (ai < 100000)
Output
開始爲"Case #i: " 後面跟着一個整數,代表最長的連續子序列爲好序列的長度
Sample Input
1 10 2 3 4 4 3 2 2 3 4 4
Output for Sample Input
Case #1: 9
比賽的時候只知道用manacher,之後就感覺下標處理起來麻煩就沒做了……,正確解法是枚舉i的對稱點i+p[i]-1,再從對稱點再往回掃一遍,看看存不存在也能往回覆蓋至i點,有的話就記錄[當前點-i]爲1.5段的長度即可。
代碼:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=100010;
int arr[N],p[N*2];
int s[N*2];
int n;
void manacher()
{
MM(p,0);
MM(s,0);
int i, len=0;
s[len++]=-2;
s[len++]=-1;
for (i=0; i<n; i++)
{
s[len++]=arr[i];
s[len++]=-1;
}
int mx=0, idd=0;
for (i=0; i<len; i++)
{
if(mx>i)
p[i]=min(p[2*idd-i],mx-i);
else
p[i]=1;
while (s[i+p[i]]==s[i-p[i]])
p[i]++;
if(i+p[i]>mx)
{
mx=p[i]+i;
idd=i;
}
}
}
int main(void)
{
int tcase, i, j, cnt=0;
scanf("%d",&tcase);
while (tcase--)
{
MM(arr,0);
scanf("%d",&n);
for (i=0; i<n; i++)
scanf("%d",&arr[i]);
manacher();
int ans=0;
for (i=1; i<2*n+2; i+=2)
{
for (j=i+p[i]-1; j-i>ans; j-=2)//往回遍歷
{
if(j-(p[j]-1)<=i)
{
if(j-i>ans)
{
ans=j-i;
break;
}
}
}
}
printf("Case #%d: %d\n",++cnt,3*(ans>>1));
}
return 0;
}