传送门:【COGS】256 [POI2001] 金矿
题目分析:将每个点作为一个矩阵的右下角添加这个矩阵的下边以及上边,这样本题转化成了区间加减以及求区间最大的问题。
代码如下:
#include
#include
#include
#include
using namespace std ;
#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define CPY( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , cnt
#define mid ( ( l + r ) >> 1 )
const int MAXN = 15005 ;
struct Line {
int l , r , h , v ;
Line () {}
Line ( int l , int r , int h , int v ) : l ( l ) , r ( r ) , h ( h ) , v ( v ) {}
bool operator < ( const Line& a ) const {
return h != a.h ? h < a.h : v > a.v ;
}
} L[MAXN << 1] ;
int a[MAXN << 1] , cnt ;
int maxv[MAXN << 3] , addv[MAXN << 3] ;
int s , w ;
int n ;
void scanf ( int& x , char c = 0 , bool flag = 0 ) {
while ( ( c = getchar () ) != '-' && ( c < '0' || c > '9' ) ) ;
if ( c == '-' ) flag = 1 , x = 0 ;
else x = c - '0' ;
while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
if ( flag ) x = -x ;
}
int unique ( int n ) {
int cnt = 1 ;
sort ( a + 1 , a + n + 1 ) ;
FOR ( i , 2 , n ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ;
return cnt ;
}
int search ( int x , int l , int r ) {
while ( l < r ) {
int m = mid ;
if ( a[m] >= x ) r = m ;
else l = m + 1 ;
}
return l ;
}
void pushdown ( int o ) {
if ( addv[o] ) {
addv[ls] += addv[o] ;
addv[rs] += addv[o] ;
maxv[ls] += addv[o] ;
maxv[rs] += addv[o] ;
addv[o] = 0 ;
}
}
void update ( int L , int R , int v , int o , int l , int r ) {
if ( L <= l && r <= R ) {
maxv[o] += v ;
addv[o] += v ;
return ;
}
int m = mid ;
pushdown ( o ) ;
if ( L <= m ) update ( L , R , v , lson ) ;
if ( m < R ) update ( L , R , v , rson ) ;
maxv[o] = max ( maxv[ls] , maxv[rs] ) ;
}
void solve () {
int x , y ;
scanf ( s ) ;
scanf ( w ) ;
scanf ( n ) ;
cnt = 0 ;
CLR ( addv , 0 ) ;
CLR ( maxv , 0 ) ;
REP ( i , 0 , n ) {
scanf ( "%d%d" , &x , &y ) ;
a[++ cnt] = x ;
a[++ cnt] = x + s ;
L[i << 1] = Line ( x , x + s , y , 1 ) ;
L[i << 1 | 1] = Line ( x , x + s , y + w , -1 ) ;
}
cnt = unique ( cnt ) ;
n <<= 1 ;
sort ( L , L + n ) ;
int ans = 0 ;
REP ( i , 0 , n ) {
int l = search ( L[i].l , 1 , cnt ) ;
int r = search ( L[i].r , 1 , cnt ) ;
update ( l , r , L[i].v , root ) ;
ans = max ( ans , maxv[1] ) ;
}
printf ( "%d\n" , ans ) ;
}
int main () {
freopen ( "kop.in" , "r" , stdin ) ;
freopen ( "kop.out" , "w" , stdout ) ;
solve () ;
return 0 ;
}