【HDU】5751 Eades【FFT】

题目链接:Eades

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
using namespace std ;

typedef long long LL ;
typedef pair < int , int > pii ;

#define clr( a , x ) memset ( a , x , sizeof a )
#define root 1 , 1 , n
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r

const int MAXN = 300005 ;
const int INF = 2e9 + 9 ;

int pos[MAXN] ;

namespace FFT {
struct comp {
    double r , i ;
    comp () {}
    comp ( double r , double i ) : r ( r ) , i ( i ) {}
    comp operator + ( const comp& a ) const {
        return comp ( r + a.r , i + a.i ) ;
    }
    comp operator - ( const comp& a ) const {
        return comp ( r - a.r , i - a.i ) ;
    }
    comp operator * ( const comp& a ) const {
        return comp ( r * a.r - i * a.i , r * a.i + i * a.r ) ;
    }
    comp conj () {
        return comp ( r , -i ) ;
    }
} A[MAXN] , B[MAXN] ;

const double pi = acos ( -1.0 ) ;

void FFT ( comp a[] , int n , int t ) {
    for ( int i = 1 ; i < n ; ++ i ) {
        if ( i < pos[i] ) swap ( a[i] , a[pos[i]] ) ;
    }
    for ( int d = 0 ; ( 1 << d ) < n ; ++ d ) {
        int m = 1 << d , m2 = m << 1 ;
        double o = pi * 2 / m2 * t ;
        comp wn ( cos ( o ) , sin ( o ) ) ;
        for ( int i = 0 ; i < n ; i += m2 ) {
            comp w ( 1 , 0 ) ;
            for ( int j = 0 ; j < m ; ++ j ) {
                comp& A = a[i + j + m] ;
                comp& B = a[i + j] ;
                comp t = w * A ;
                A = B - t ;
                B = B + t ;
                w = w * wn ;
            }
        }
    }
    if ( t == -1 ) {
        for ( int i = 0 ; i < n ; ++ i ) {
            a[i].r /= n ;
        }
    }
}

void mul ( LL *a , LL *b , LL *c , int k ) {
    int i , j = __builtin_ctz ( k ) - 1 ;
    for ( int i = 0 ; i < k ; ++ i ) {
        pos[i] = pos[i >> 1] >> 1 | ( ( i & 1 ) << j ) ;
    }
    for ( int i = 0 ; i < k ; ++ i ) {
        A[i] = comp ( a[i] , b[i] ) ;
    }
    FFT ( A , k , 1 ) ;
    for ( int i = 0 ; i < k ; ++ i ) {
        j = ( k - i ) & ( k - 1 ) ;
        B[i] = ( A[i] * A[i] - ( A[j] * A[j] ).conj () ) * comp ( 0 , -0.25 ) ;
    }
    FFT ( B , k , -1 ) ;
    for ( int i = 0 ; i < k ; ++ i ) {
        c[i] = ( ( long long ) ( B[i].r + 0.5 ) ) ;
    }
}
}

pii T[MAXN] ;
int val[MAXN] ;
vector < int > G[MAXN] ;
LL ans[MAXN] ;
LL A[MAXN] , B[MAXN] , C[MAXN] ;
int n , cur ;

void build ( int o , int l , int r ) {
    if ( l == r ) {
        scanf ( "%d" , &val[l] ) ;
        T[o].first = val[l] ;
        T[o].second = -l ;
        return ;
    }
    int m = l + r >> 1 ;
    build ( lson ) ;
    build ( rson ) ;
    T[o] = max ( T[ls] , T[rs] ) ;
}

pii query ( int L , int R , int o , int l , int r ) {
    if ( L <= l && r <= R ) return T[o] ;
    int m = l + r >> 1 ;
    pii ans ( 0 , 0 ) ;
    if ( L <= m ) ans = max ( ans , query ( L , R , lson ) ) ;
    if ( m <  R ) ans = max ( ans , query ( L , R , rson ) ) ;
    return ans ;
}

void dfs ( int u , int L , int R ) {
    if ( L + 1 > R - 1 ) return ;
    if ( L + 1 == R - 1 ) {
        ans[1] ++ ;
        return ;
    }
    int x = L ;
    int v = query ( L + 1 , R - 1 , root ).first ;
    G[u].clear () ;
    G[u].push_back ( x ) ;
    while ( 1 ) {
        if ( x + 1 > R - 1 ) break ;
        int y = -query ( x + 1 , R - 1 , root ).second ;
        if ( val[y] < v ) break ;
        G[u].push_back ( y ) ;
        x = y ;
    }
    G[u].push_back ( R ) ;
    int t = G[u].size () - 1 ;
    for ( int i = 0 ; i < t ; ++ i ) {
        B[t - i - 1] = A[i] = G[u][i + 1] - G[u][i] ;
    }
    int nn = 1 ;
    while ( nn < t ) nn <<= 1 ;
    nn <<= 1 ;
    for ( int i = t ; i < nn ; ++ i ) {
        B[i] = A[i] = 0 ;
    }
    FFT::mul ( A , B , C , nn ) ;
    for ( int i = 0 ; i < t - 1 ; ++ i ) {
        ans[t - 1 - i] += C[i] ;
    }
    for ( int i = 1 ; i < G[u].size () ; ++ i ) {
        ++ cur ;
        dfs ( cur , G[u][i - 1] , G[u][i] ) ;
    }
}

void solve () {
    scanf ( "%d" , &n ) ;
    build ( root ) ;
    cur = 1 ;
    for ( int i = 1 ; i <= n ; ++ i ) {
        ans[i] = 0 ;
    }
    dfs ( cur , 0 , n + 1 ) ;
    LL res = 0 ;
    for ( int i = 1 ; i <= n ; ++ i ) {
        res += ans[i] ^ i ;
    }
    printf ( "%I64d\n" , res ) ;
}

int main () {
    int T ;
    scanf ( "%d" , &T ) ;
    for ( int i = 1 ; i <= T ; ++ i ) {
        solve () ;
    }
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值