[BZOJ4237]稻草人 题解

我们考虑分治一下

\(x\)坐标排序 然后对于每一段的两部分都按\(y\)排序

左右两边都维护一个单调栈

然后考虑右边对左边的贡献就行了

#include <bits/stdc++.h>
#define int long long
using namespace std ;
const int MAXN = 2e5 + 5 ;
int n ;
struct Node {
    int x , y ;
} d[ MAXN ] ;
int ans ;
inline bool cmp ( Node a , Node b ) { return a.x < b.x ; }
inline bool cmp1 ( Node a , Node b ) { return a.y > b.y ; }
int st1[ MAXN ] , st2[ MAXN ] , top1 , top2 ;
inline int read () {
    int tot = 0 , f = 1 ; char c = getchar () ;
    while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -1 ; c = getchar () ; }
    while ( c >= '0' && c <= '9' ) { tot = tot * 10 + c - '0' ; c = getchar () ; }
    return tot * f ;
}
inline void cdq ( int l , int r ) {
    if ( l >= r ) return ;
    int mid = ( l + r ) >> 1 ;
    sort ( d + l , d + mid + 1 , cmp1 ) ;
    sort ( d + mid + 1 , d + r + 1 , cmp1 ) ;
    int tot = mid + 1 ; top1 = top2 = 0 ;
    for ( int i = l ; i <= mid ; i ++ ) {
        while ( top1 && d[ st1[ top1 ] ].x < d[ i ].x ) top1 -- ;
        st1[ ++ top1 ] = i ;
        while ( tot <= r && d[ tot ].y >= d[ i ].y ) {
            while ( top2 && d[ st2[ top2 ] ].x > d[ tot ].x ) top2 -- ;
            st2[ ++ top2 ] = tot ;
            tot ++ ;
        }
        if ( top1 == 1 ) { ans += top2 ; continue ; }
        int t = d[ st1[ top1 - 1 ] ].y ;
        int lx = 1 , rx = top2 , ans1 = 0 ;
        while ( lx <= rx ) {
            int midx = ( lx + rx ) >> 1 ;
            if ( d[ st2[ midx ] ].y <= t ) ans1 = midx , rx = midx - 1 ;
            else lx = midx + 1 ;
        }
        if ( ans1 && ans1 <= top2 ) ans += ( top2 - ans1 + 1 ) ;
    }
    sort ( d + l , d + r + 1 , cmp ) ;
    cdq ( l , mid ) ;
    cdq ( mid + 1 , r ) ;
}
signed main () {
    n = read () ;
    for ( int i = 1 ; i <= n ; i ++ ) d[ i ].x = read () , d[ i ].y = read () ;
    sort ( d + 1 , d + 1 + n , cmp ) ;
    ans = 0 ;
    cdq ( 1 , n ) ;
    printf ( "%lld\n" , ans ) ;
    return 0 ;
}

posted @ 2020-08-09 12:56  hulean  阅读(135)  评论(0编辑  收藏  举报