【HDU】5994 Generator and Monitor【KD树】

题目链接:【HDU】5994 Generator and Monitor

看懂题就会做系列,模板题。

#include <bits/stdc++.h>
using namespace std ;

typedef long long LL ;

#define clr( a , x ) memset ( a , x , sizeof a )

const int MAXN = 200005 ;
const int MAXM = 10000005 ;
const int INF = 0x3f3f3f3f ;

struct Node {
    int p[2] ;
    int f , l , r , idx ;
    int Min[2] , Max[2] ;
    int minv , v , pos ;
    int addv ;
    int operator [] ( const int idx ) const {
        return p[idx] ;
    }
    void init () {
        Min[0] = Max[0] = p[0] ;
        Min[1] = Max[1] = p[1] ;
        pos = minv = v = INF ;
        addv = 0 ;
    }
    void up ( Node& a ) {
        Min[0] = min ( Min[0] , a.Min[0] ) ;
        Max[0] = max ( Max[0] , a.Max[0] ) ;
        Min[1] = min ( Min[1] , a.Min[1] ) ;
        Max[1] = max ( Max[1] , a.Max[1] ) ;
    }
    void down ( int x ) {
        if ( x ) minv += x , v += x , addv += x ;
    }
} ;

struct Op {
    int x , y , c ;
} ;

Op p[MAXN] ;
char buf[MAXM + 1] , *cur = buf ;
Node T[MAXN] ;
int idx[MAXN] ;
int root , cmpw , tot ;
int res[MAXN] ;
int n , m ;

bool cmp ( const Node& a , const Node& b ) {
    return a.p[cmpw] < b.p[cmpw] ;
}

int build ( int l , int r , int w , int f ) {
    int o = l + r >> 1 ;
    cmpw = w ;
    nth_element ( T + l , T + o , T + r + 1 , cmp ) ;
    idx[T[o].idx] = o ;
    T[o].init () ;
    T[o].f = f ;
    T[o].l = l != o ? build ( l , o - 1 , !w , o ) : 0 ;
    T[o].r = r != o ? build ( o + 1 , r , !w , o ) : 0 ;
    if ( T[o].l ) T[o].up ( T[T[o].l] ) ;
    if ( T[o].r ) T[o].up ( T[T[o].r] ) ;
    return o ;
}

int check ( int x1 , int x2 , int y1 , int y2 , int x ) {
    if ( x2 <= x && y1 >= x ) return 0 ;
    if ( x1 <= x && y2 >= x ) return 2 ;
    return 1 ;
}

void up ( int o ) {
    T[o].minv = T[o].v ;
    T[o].pos = T[o].idx ;
    if ( T[o].l && T[T[o].l].minv < T[o].minv ) {
        T[o].minv = T[T[o].l].minv ;
        T[o].pos = T[T[o].l].pos ;
    }
    if ( T[o].r && T[T[o].r].minv < T[o].minv ) {
        T[o].minv = T[T[o].r].minv ;
        T[o].pos = T[T[o].r].pos ;
    }
}

void down ( int o ) {
    int x = T[o].addv ;
    if ( !x ) return ;
    if ( T[o].l ) T[T[o].l].down ( x ) ;
    if ( T[o].r ) T[T[o].r].down ( x ) ;
    T[o].addv = 0 ;
}

void sign_down ( int o ) {
    if ( T[o].f ) sign_down ( T[o].f ) ;
    down ( o ) ;
}

void upd ( int o , int x , int v ) {
    int d = check ( T[o].Min[0] , T[o].Max[0] , T[o].Min[1] , T[o].Max[1] , x ) ;
    if ( !d ) {
        T[o].down ( v ) ;
        return ;
    }
    if ( d == 1 ) return ;
    if ( T[o][0] <= x && T[o][1] >= x ) {
        T[o].v += v ;
        T[o].minv += v ;
    }
    down ( o ) ;
    if ( T[o].l ) upd ( T[o].l , x , v ) ;
    if ( T[o].r ) upd ( T[o].r , x , v ) ;
    up ( o ) ;
}

void add ( int o , int v ) {
    for ( sign_down ( o ) , T[o].v = v ; o ; o = T[o].f ) up ( o ) ;
}

void scanf ( int& x ) {
    while ( *cur < '0' ) ++ cur ;
    x = *cur - '0' , ++ cur ;
    while ( *cur >= '0' ) ( x *= 10 ) += *cur - '0' , ++ cur ;
}

void solve () {
    tot = 0 ;
    scanf ( n ) ;
    scanf ( m ) ;
    for ( int i = 1 ; i <= n ; ++ i ) {
        char op ;
        while ( ( op = *cur ) < 'A' ) ++ cur ;
        ++ cur ;
        if ( op == 'C' ) {
            scanf ( p[i].x ) ;
            scanf ( p[i].y ) ;
            scanf ( p[i].c ) ;
            ++ tot ;
            T[tot].p[0] = p[i].x ;
            T[tot].p[1] = p[i].y ;
            T[tot].idx = i ;
        } else p[i].c = 0 , scanf ( p[i].x ) ;
    }
    root = build ( 1 , tot , 0 , 0 ) ;
    int now = 0 ;
    for ( int i = 1 ; i <= n ; ++ i ) {
        if ( p[i].c ) add ( idx[i] , p[i].c ) ;
        else upd ( root , p[i].x ^ now , -1 ) ;
        int val = 0 , top = 0 ;
        while ( !T[root].minv ) {
            val ^= T[root].pos ;
            res[++ top] = T[root].pos ;
            add ( idx[T[root].pos] , INF ) ;
        }
        now ^= val ;
        if ( top ) {
            printf ( "%d" , i ) ;
            sort ( res + 1 , res + top + 1 ) ;
            for ( int j = 1 ; j <= top ; ++ j ) {
                printf ( " %d" , res[j] ) ;
            }
            puts ( "" ) ;
        }
    }
}

int main () {
    fread ( buf , 1 , MAXM , stdin ) ;
    int T ;
    scanf ( T ) ;
    for ( int i = 1 ; i <= T ; ++ i ) {
        printf ( "Case #%d:\n" , i ) ;
        solve () ;
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值