【BZOJ】4154: [Ipsc2015]Generating Synergy【KD树】

传送门:【BZOJ】4154: [Ipsc2015]Generating Synergy

分析:以dfs序和深度为关键字,作为平面点,于是对于每个询问就是在平面上的矩形区域修改以及查询。

my   code:

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

typedef long long LL ;

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

const int MAXN = 100005 ;
const int mod = 1e9 + 7 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;

struct Node {
    int p[2] ;
    int f , l , r ;
    int Min[2] , Max[2] ;
    int tim , col ;
    int t , c ;
    int operator [] ( const int idx ) const {
        return p[idx] ;
    }
    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] ) ;
    }
} ;

Node T[MAXN] ;
Edge E[MAXN] ;
int H[MAXN] , cntE ;
int idx[MAXN] , cmpw , root ;
int in[MAXN] , ou[MAXN] , dfs_clock ;
int dep[MAXN] ;
int n , q ;

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
}

void dfs ( int u ) {
    in[u] = ++ dfs_clock ;
    for ( int i = H[u] ; ~i ; i = E[i].n ) {
        int v = E[i].v ;
        dep[v] = dep[u] + 1 ;
        dfs ( v ) ;
    }
    ou[u] = ++ dfs_clock ;
}

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

void up ( int o ) {
    if ( T[o].l ) T[o].up ( T[T[o].l] ) ;
    if ( T[o].r ) T[o].up ( T[T[o].r] ) ;
}

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

void upd ( int o , int t , int c , int x1 , int x2 , int y1 , int y2 ) {
    if ( T[o].Min[0] >= x1 && T[o].Max[0] <= x2 && T[o].Min[1] >= y1 && T[o].Max[1] <= y2 ) {
        T[o].tim = T[o].t = t ;
        T[o].col = T[o].c = c ;
        return ;
    }
    if ( T[o].Min[0] > x2 || T[o].Max[0] < x1 || T[o].Min[1] > y2 || T[o].Max[1] < y1 ) return ;
    if ( T[o][0] >= x1 && T[o][0] <= x2 && T[o][1] >= y1 && T[o][1] <= y2 ) {
        T[o].tim = t ;
        T[o].col = c ;
    }
    if ( T[o].l ) upd ( T[o].l , t , c , x1 , x2 , y1 , y2 ) ;
    if ( T[o].r ) upd ( T[o].r , t , c , x1 , x2 , y1 , y2 ) ;
}

int query ( int o ) {
    int t = T[o].tim , c = T[o].col ;
    while ( T[o].f ) {
        o = T[o].f ;
        if ( T[o].t > t ) {
            t = T[o].t ;
            c = T[o].c ;
        }
    }
    return c ;
}

void solve () {
    int x , l , c ;
    scanf ( "%d%*d%d" , &n , &q ) ;
    cntE = dfs_clock = 0 ;
    clr ( H , -1 ) ;
    for ( int i = 2 ; i <= n ; ++ i ) {
        scanf ( "%d" , &x ) ;
        addedge ( x , i ) ;
    }
    dfs ( 1 ) ;
    T[0].tim = T[0].t = 0 ;
    T[0].col = T[0].c = 1 ;
    for ( int i = 1 ; i <= n ; ++ i ) {
        T[i].p[0] = in[i] ;
        T[i].p[1] = dep[i] ;
        T[i].col = T[i].c = 1 ;
        T[i].tim = T[i].t = 0 ;
        T[i].f = i ;
    }
    root = build ( 1 , n , 0 , 0 ) ;
    int ans = 0 ;
    for ( int i = 1 ; i <= q ; ++ i ) {
        scanf ( "%d%d%d" , &x , &l , &c ) ;
        if ( c ) {
            if ( l == 0 || in[x] == ou[x] ) {
                T[idx[x]].tim = i ;
                T[idx[x]].col = c ;
                continue ;
            }
            upd ( root , i , c , in[x] , ou[x] , dep[x] , dep[x] + l ) ;
        } else {
            int tmp = query ( idx[x] ) ;
            ans = ( ans + 1LL * i * tmp ) % mod ;
        }
    }
    printf ( "%d\n" , ans ) ;
}

int main () {
    int T ;
    scanf ( "%d" , &T ) ;
    for ( int i = 1 ; i <= T ; ++ i ) {
        solve () ;
    }
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值