【线段树】 HDOJ 3627 Giant For

CF原题。。。刚开始做的时候SB的线段树套set。。。。结果在HDOJ上MLE。。。CF上TLE。。。后来换了姿势在HDOJ上过了。。。。但是CF还是TLE啊。。。优化不了了,求大牛指点。。。

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 200005
#define maxm 1000005
#define eps 1e-10
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
//#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

struct node
{
    int x, y, k, id;
}p[maxn];
char ss[maxn];
int x[maxn];
int maxv[maxn << 2];
set<int> s[maxn];
set<int>::iterator it;
int cnt, n, ans_x, ans_y;

int cmp1(node a, node b)
{
    return a.x < b.x;
}

int cmp2(node a, node b)
{
    return a.id < b.id;
}

void init(void)
{
    for(int i = 0; i < maxn; i++) s[i].clear();
}

void read(void)
{
    for(int i = 1; i <= n; i++) {
        scanf("%s%d%d", ss, &p[i].x, &p[i].y);
        if(ss[0] == 'a') p[i].k = 1;
        if(ss[0] == 'r') p[i].k = 2;
        if(ss[0] == 'f') p[i].k = 3;
        p[i].id = i;
    }
    sort(p+1, p+n+1, cmp1);
    for(int i = 1; i <= n; i++) x[i] = p[i].x;
    int j = 2;
    for(int i = 2; i <= n; i++) if(x[i] != x[i-1]) x[j++] = x[i];
    cnt = j-1;
    for(int i = 1; i <= n; i++) p[i].x = lower_bound(x+1, x+cnt+1, p[i].x) - x;
    sort(p+1, p+n+1, cmp2);
}

void pushup(int o)
{
    maxv[o] = max(maxv[ls], maxv[rs]);
}

void build(int o, int L, int R)
{
    maxv[o] = -1;
    if(L == R) return;
    int mid = (L + R) >> 1;
    build(lson);
    build(rson);
    pushup(o);
}

void add(int o, int L, int R, int pos, int x)
{    
    if(L == R) {
        maxv[o] = max(maxv[o], x);    
        return;
    }
    int mid = (L + R) >> 1;
    if(pos <= mid) add(lson, pos, x);
    else add(rson, pos, x);
    pushup(o);
}

void remove(int o, int L, int R, int pos, int x)
{
    if(L == R) {
        if(s[L].empty()) maxv[o] = -1;
        else maxv[o] = *(--s[L].end());
        return;
    }
    int mid = (L + R) >> 1;
    if(pos <= mid) remove(lson, pos, x);
    else remove(rson, pos, x);
    pushup(o);
}

void query(int o, int L, int R, int ql, int qr, int y)
{
    if(ans_x != -1) return;
    if(L == R) {
        if(maxv[o] <= y) return;
        ans_y = *(upper_bound(s[L].begin(), s[L].end(), y));
        ans_x = L;
        return;
    }
    int mid = (L + R) >> 1;
    if(ql <= L && qr >= R) {
        if(maxv[o] <= y) return;
        else {
            query(lson, ql, qr, y);
            query(rson, ql, qr, y);
        }
    }
    if(ql <= mid) query(lson, ql, qr, y);
    if(qr > mid) query(rson, ql, qr, y);
}

void work(void)
{
    build(1, 1, cnt+1);
    for(int i = 1; i <= n; i++) {
        if(p[i].k == 1) {
            s[p[i].x].insert(p[i].y);
            add(1, 1, cnt + 1, p[i].x, p[i].y);
        
        }
        if(p[i].k == 2) {
            s[p[i].x].erase(p[i].y);
            remove(1, 1, cnt + 1, p[i].x, p[i].y);
        }
        if(p[i].k == 3) {
            ans_x = ans_y = -1;
            query(1, 1, cnt + 1, p[i].x+1, cnt + 1, p[i].y);
            if(ans_x == -1) printf("-1\n");
            else printf("%d %d\n", x[ans_x], ans_y);
        }
    }
}

int main(void)
{
    int _ = 0;
    while(scanf("%d", &n), n != 0) {
        init();
        read();
        if(_) printf("\n");        
        printf("Case %d:\n", ++_);
        work();
    }

    return 0;
}


你可能感兴趣的:(线段树,HDU)