题目链接:【玲珑杯】1048 - Best substring
wa了一辈子,最后发现是利用归并排序后的退栈策略错了。应该是判栈顶和当前元素的关系,然而我偷懒只判了相邻两个元素的关系,gg。
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 200005 ;
struct Line {
LL k , b ;
Line () {}
Line ( LL k , LL b ) : k ( k ) , b ( b ) {}
bool operator < ( const Line& a ) const {
return k != a.k ? k < a.k : b < a.b ;
}
LL f ( int x ) {
return k * x + b ;
}
} ;
char Ma[MAXN << 1] ;
int R[MAXN << 1] ;
Line a[MAXN] ;
LL sum[MAXN] ;
LL val[MAXN] ;
LL tot[MAXN] ;
char s[MAXN] ;
int id[MAXN] ;
int c[MAXN] ;
int S[MAXN] ;
LL ans ;
int n ;
int check ( int i , int j , int k ) {
return ( double ) ( a[i].b - a[j].b ) / ( a[j].k - a[i].k ) >= ( double ) ( a[i].b - a[k].b ) / ( a[k].k - a[i].k ) ;
}
void merge ( int a[] , int n , int b[] , int m ) {
int i = 0 , j = 0 , k = 0 , t = 0 ;
while ( i < n && j < m ) c[k ++] = sum[a[i]] < sum[b[j]] ? a[i ++] : b[j ++] ;
while ( i < n ) c[k ++] = a[i ++] ;
while ( j < m ) c[k ++] = b[j ++] ;
while ( t < n + m ) a[t] = c[t] , t ++ ;
}
void dfs ( int l , int r ) {
if ( l == r ) return ;
int m = l + r >> 1 ;
dfs ( l , m ) ;
dfs ( m + 1 , r ) ;
int cnt = 0 , t = 0 ;
tot[m] = 0 ;
for ( int i = m + 1 ; i <= r ; ++ i ) {
tot[i] = tot[i - 1] + ( i - m ) * val[i] ;
}
for ( int i = m + 1 ; i <= r ; ++ i ) {
a[++ cnt] = Line ( sum[id[i]] - sum[m] , tot[id[i]] ) ;
}
for ( int i = 1 ; i <= cnt ; ++ i ) {
while ( t && a[S[t]].k == a[i].k && a[S[t]].b < a[i].b ) -- t ;
while ( t > 1 && check ( S[t - 1] , S[t] , i ) ) -- t ;
S[++ t] = i ;
}
LL res = 0 ;
for ( int i = m , j = 1 , k = 1 ; i >= l ; -- i , ++ j ) {
res += sum[m] - sum[i - 1] ;
while ( k < t && a[S[k]].f ( j ) < a[S[k + 1]].f ( j ) ) ++ k ;
ans = max ( ans , res + a[S[k]].f ( j ) ) ;
}
merge ( id + l , m - l + 1 , id + m + 1 , r - m ) ;
}
void manacher ( char s[] , int n ) {
int l = 0 ;
Ma[l ++] = '$' ;
Ma[l ++] = '#' ;
for ( int i = 0 ; i < n ; ++ i ) {
Ma[l ++] = s[i] ;
Ma[l ++] = '#' ;
}
Ma[l] = 0 ;
for ( int i = 0 , mx = 0 , id = 0 ; i < l ; ++ i ) {
R[i] = mx > i ? min ( R[2 * id - i] , mx - i ) : 1 ;
while ( Ma[i + R[i]] == Ma[i - R[i]] ) R[i] ++ ;
if ( i + R[i] > mx ) mx = i + R[i] , id = i ;
}
}
void solve () {
scanf ( "%d%s" , &n , s ) ;
manacher ( s , n ) ;
ans = 0 ;
for ( int i = 1 ; i <= n ; ++ i ) {
val[i] = R[i * 2] - 1 ;
if ( i % 2 == 0 ) val[i] = -val[i] ;
sum[i] = sum[i - 1] + val[i] ;
ans = max ( ans , val[i] ) ;
id[i] = i ;
}
dfs ( 1 , n ) ;
printf ( "%lld\n" , ans ) ;
}
int main () {
int T ;
scanf ( "%d" , &T ) ;
while ( T -- ) solve () ;
return 0 ;
}