【codeforces】678 F. Lena and Queries【线段树维护凸壳】

题目链接:【codeforces】678 F. Lena and Queries

#include 
using namespace std ;

typedef long long LL ;
typedef pair < int , int > pii ;

#define getid( l , r ) l + r | ( l != r )

const int MAXN = 300005 ;
const int DEL = 1e9 + 7 ;
const LL INF = 2e18 ;

struct Line {
    int k , b ;
    Line () {}
    Line ( int k , int b ) : k ( k ) , b ( b ) {}
    LL f ( int x ) {
        return 1LL * k * x + b ;
    }
    bool operator < ( const Line& a ) const {
        return k != a.k ? k < a.k : b < a.b ;
    }
} ;

vector < Line > T[MAXN << 1] ;
pii seg[MAXN] , op[MAXN] ;
int n , cnt ;

void add ( int L , int R , int k , int b , int l , int r ) {
    int o = getid ( l , r ) , m = l + r >> 1 ;
    if ( L <= l && r <= R ) T[o].push_back ( Line ( k , b ) ) ;
    else {
        if ( L <= m ) add ( L , R , k , b , l , m ) ;
        if ( m <  R ) add ( L , R , k , b , m + 1 , r ) ;
    }
}

int check ( vector < Line >& a , int i , int j , int k ) {
    return 1LL * ( a[i].b - a[j].b ) * ( a[k].k - a[i].k ) >= 1LL * ( a[i].b - a[k].b ) * ( a[j].k - a[i].k ) ;
}

void calc ( vector < Line >& T ) {
    static int S[MAXN] , i , t ;
    sort ( T.begin () , T.end () ) ;
    for ( i = 0 , t = 0 ; i < T.size () ; ++ i ) {
        while ( t && T[S[t]].k == T[i].k || t > 1 && check ( T , S[t - 1] , S[t] , i ) ) -- t ;
        S[++ t] = i ;
    }
    vector < Line > nxt ;
    for ( i = 1 ; i <= t ; ++ i ) {
        nxt.push_back ( T[S[i]] ) ;
    }
    T = nxt ;
}

LL get_max_val ( int x , int o ) {
    if ( !T[o].size () ) return -INF ;
    int l = 0 , r = T[o].size () - 1 ;
    while ( l < r ) {
        int m = l + r >> 1 ;
        if ( T[o][m].f ( x ) > T[o][m + 1].f ( x ) ) r = m ;
        else l = m + 1 ;
    }
    return T[o][l].f ( x ) ;
}

LL query ( int x , int pos , int l , int r ) {
    LL res = -INF ;
    while ( l < r ) {
        int o = getid ( l , r ) , m = l + r >> 1 ;
        res = max ( res , get_max_val ( x , o ) ) ;
        if ( pos <= m ) r = m ;
        else l = m + 1 ;
    }
    res = max ( res , get_max_val ( x , getid ( l , r ) ) ) ;
    return res ;
}

void solve () {
    cnt = 0 ;
    for ( int i = 1 ; i <= n << 1 ; ++ i ) T[i].clear () ;
    for ( int i = 1 , c ; i <= n ; ++ i ) {
        scanf ( "%d%d" , &c , &seg[i].first ) ;
        if ( c == 1 ) scanf ( "%d" , &seg[i].second ) ;
        else if ( c == 2 ) {
            int x = seg[i].first ;
            add ( x , i , seg[x].first , seg[x].second , 1 , n ) ;
            seg[x].first = seg[i].first = DEL ;
        } else op[++ cnt] = pii ( seg[i].first , i ) , seg[i].first = DEL ;
    }
    for ( int i = 1 ; i <= n ; ++ i ) {
        if ( seg[i].first != DEL ) add ( i , n , seg[i].first , seg[i].second , 1 , n ) ;
    }
    for ( int i = 1 ; i <= n << 1 ; ++ i ) if ( T[i].size () ) {
        calc ( T[i] ) ;
    }
    for ( int i = 1 ; i <= cnt ; ++ i ) {
        LL res = query ( op[i].first , op[i].second , 1 , n ) ;
        if ( res == -INF ) printf ( "EMPTY SET\n" ) ;
        else printf ( "%lld\n" , res ) ;
    }
}

int main () {
    while ( ~scanf ( "%d" , &n ) ) solve () ;
    return 0 ;
}

你可能感兴趣的:(计算几何,线段树)