HDU - 6183 动态开点线段树+维护最值
题目链接
考虑对每种颜色都沿y轴建立线段树,维护区间点的x坐标的最小值。
线段树需要动态开点不然会mle
#include <algorithm>
#include <cstdio>
#include <cstring>
const int N = 1000005 * 51 ;
const int INF = 0x3f3f3f3f ;
int c[ N] , ls[ N] , rs[ N] , tot;
int rt[ 51 ] ;
int newNode ( ) {
c[ ++ tot] = INF;
ls[ tot] = rs[ tot] = 0 ;
return tot;
}
void update ( int & k, int l, int r, int y, int val) {
if ( ! k) k = newNode ( ) ;
c[ k] = std:: min ( c[ k] , val) ;
if ( l == r) return ;
int mid = ( l + r) >> 1 ;
if ( mid >= y)
update ( ls[ k] , l, mid, y, val) ;
else
update ( rs[ k] , mid + 1 , r, y, val) ;
}
int query ( int k, int l, int r, int left, int right) {
if ( ! k) return INF;
if ( left <= l && r <= right)
return c[ k] ;
int mid = ( l + r) >> 1 ;
if ( right <= mid)
return query ( ls[ k] , l, mid, left, right) ;
else if ( left > mid)
return query ( rs[ k] , mid + 1 , r, left, right) ;
else
return std:: min ( query ( ls[ k] , l, mid, left, right) , query ( rs[ k] , mid + 1 , r, left, right) ) ;
}
int main ( ) {
int op, x, y, c, yy;
while ( true ) {
scanf ( "%d" , & op) ;
if ( op == 3 ) break ;
if ( op == 0 ) {
tot = 0 ;
for ( int i = 0 ; i < 51 ; ++ i) rt[ i] = newNode ( ) ;
} else if ( op == 1 ) {
scanf ( "%d%d%d" , & x, & y, & c) ;
update ( rt[ c] , 1 , 1000000 , y, x) ;
} else {
scanf ( "%d%d%d" , & x, & y, & yy) ;
int ans = 0 ;
for ( int i = 0 ; i < 51 ; ++ i) {
if ( x >= query ( rt[ i] , 1 , 1000000 , y, yy) ) ans++ ;
}
printf ( "%d\n" , ans) ;
}
}
return 0 ;
}