[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 ;
}