2018 焦作 H. Can You Solve the Harder Problem?

思路:单调栈加后缀数组。有点绕(尼玛又发现了后缀数组板子的bugQAQ),如果全是 0 g.s 的初始化也为0,求h数组就凉了

//本质不同的子串个数

#include 
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn = 2000000 + 10;
typedef int lint;
struct suffix{

    lint c[maxn],sa[maxn],t1[maxn],t2[maxn],m,n,h[maxn],height[maxn],rk[maxn],s[maxn];
    void Build_SA(lint len){
        m = 0;
        lint* x = t1,*y = t2;
        n = len;
        for( lint i = 0;i < n;i++ ) m = max( m,s[i] );
        for( lint i = 0;i <= m;i++ ) c[i] = 0;
        for( lint i = 0;i < n;i++ ) c[ x[i] = s[i] ]++;
        for( lint i = 1;i <= m;i++ ) c[i] += c[i-1];
        for( lint i = n-1;i >= 0;i-- ) {
            sa[ --c[ x[i] ] ] = i;
        }
        for( lint k = 1;k < n;k <<= 1 ){
            lint cnt = 0;
            for( lint i = n - 1;i >= n-k;i-- ) y[cnt++] = i;
            for( lint i = 0;i < n;i++ ) if( sa[i] >= k ) y[cnt++] = sa[i]-k;
            for( lint i = 0;i <= m;i++ ) c[i] = 0;
            for( lint i = 0;i < n;i++ ) c[ x[i] ]++;
            for( lint i = 1;i <= m;i++ ) c[i] += c[i-1];
            for( lint i = cnt-1;i >= 0;i-- ) sa[ --c[ x[ y[i] ] ] ] = y[i];
            swap( x,y );
            lint num = 0;
            x[ sa[0] ] = 0;
            for( lint i = 1;i < n;i++ ){
                if( y[ sa[i-1] ] != y[ sa[i] ] || y[ sa[i-1]+k ] != y[ sa[i]+k ] ){
                    x[ sa[i] ] = ++num;
                }else{
                    x[ sa[i] ] = num;
                }
            }
            if( num == n-1 ) return;
            m = num;
        }
    }
    void getheight(){
        for( lint i = 0;i < n;i++ ){
            rk[ sa[i] ] = i;
        }
        lint cnt = 1;
        h[ sa[0] ] = 0;
        height[ 0 ] = 0;
        for( lint i = 0;i < n;i++ ){
            if(cnt)cnt--;
            while(  rk[i] >= 1 &&  sa[rk[i]-1]+cnt < n && i + cnt < n && s[ sa[rk[i]-1]+cnt ] == s[ i+cnt ] ) cnt++;
            h[ i ] = cnt;
            height[ rk[i] ] = cnt;
        }
        //cout << "debug" << endl;
    }

}g;
lint a[maxn];
vector ve;
void discrete(){
    sort( ve.begin(),ve.end() );
    auto p = unique( ve.begin(),ve.end() );
    ve.erase( p,ve.end() );
}
lint Q( lint x ){
    return lower_bound( ve.begin(),ve.end(),x ) - ve.begin();
}
lint st[maxn],top,n;
LL sum[maxn],ans;
void solve(){
    for( lint i = n-1;i >= 0;i-- ){
        while( top && a[ -st[top-1] ] < a[i]  ) {
            //sum -= a[ -st[top-1] ]*(  );
            top--;
        }
        st[top++] = -i;
        sum[top-1] = ((top != 1)?  (LL)a[i]*( st[top-1]-st[top-2] ) : (LL)a[i]*( n - i )) + sum[top-2] ;
        lint len = g.h[i];
        lint pos = lower_bound( st,st+top,-( i+len- 1 ) ) -st;
        pos--;
        if( pos == -1 ){
            ans += (LL)a[ -st[pos+1] ] *( n - (i+len) );
        }else{
            ans += sum[pos]+(LL)a[-st[pos+1] ]*( -st[pos]-(i+len-1)-1 );
        }
    }
}
int main()
{
    lint T;
    scanf("%d",&T);
    while( T-- ){
        ve.clear();top = 0;ans = 0;
        scanf("%d",&n);
        for( lint i = 0;i < n;i++ ){
            scanf("%d",&a[i]);
            ve.push_back( a[i] );
        }
        discrete();
        for( lint i = 0;i < n;i++ ){
            g.s[i] = Q( a[i] );
        }
        g.Build_SA(n);
        g.getheight();
        solve();
        printf("%lld\n",ans);
    }
}









 

你可能感兴趣的:(后缀数组)