BZOJ 2342 [Shoi2011]双倍回文(manacher+堆+set)
题意
N<=500000
题解
维护一个set可以用堆来解决。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 #include<set> 7 #include<queue> 8 using namespace std; 9 const int N=500100; 10 int str[N*2],m,p[N*2]; 11 int n,f[N],now,ans; 12 char s[N]; 13 struct hhh{ 14 int l,r; 15 bool operator <(const hhh &a)const{ 16 return a.r<r; 17 } 18 }c[N]; 19 set<int> se; 20 priority_queue<hhh> q; 21 void init(){ 22 str[0]=str[1]='#'; 23 for(int i=1;i<=n;i++){ 24 str[i*2]=s[i]; 25 str[i*2+1]='#'; 26 } 27 m=n*2+1; 28 } 29 void manacher(){ 30 int mx=0,id; 31 for(int i=1;i<=m;i++){ 32 if(mx>i)p[i]=min(p[id-(i-id)],id+p[id]-i); 33 else p[i]=1; 34 while(str[i-p[i]]==str[i+p[i]])p[i]++; 35 if(i+p[i]-1>mx)mx=i+p[i]-1,id=i; 36 } 37 } 38 int main(){ 39 scanf("%d",&n); 40 scanf("%s",s+1); 41 init(); 42 manacher(); 43 for(int i=1;i<=n;i++){ 44 f[i]=p[i*2+1]/2; 45 c[i].l=i; 46 c[i].r=i+f[i]; 47 } 48 for(int i=1;i<=n;i++){ 49 if(i-1+f[i-1]>=i){ 50 se.insert(i-1); 51 q.push(c[i-1]); 52 } 53 while(!q.empty()&&q.top().r<i){ 54 se.erase(q.top().l); 55 q.pop(); 56 } 57 set<int>::iterator it=se.lower_bound(i-f[i]/2); 58 if(it!=se.end()){ 59 ans=max(ans,(i-*it)*4); 60 } 61 } 62 printf("%d",ans); 63 return 0; 64 }