hdu 1540 Tunnel Warfare(线段树)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1540

题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少。

其实这题直接二分查找也可以,但用线段树可以练一练手。

大致思路就是找查询点最近的左右两个0的位置(0表示被摧毁的),然后输出区间大小即可,如果这个点已经被摧毁那么就没有

连续的区间,那么输出0。线段树查询位置有点麻烦具体看代码。

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
using namespace std;
const int M = 5e4 + 10;
struct TnT {
    int l , r , num;
}T[M << 2];
int n , m;
void build(int l , int r , int p) {
    int mid = (l + r) >> 1;
    T[p].l = l , T[p].r = r;
    if(T[p].l == T[p].r) {
        T[p].num = 1;
        return;
    }
    build(l , mid , p << 1);
    build(mid + 1 , r , (p << 1) | 1);
    T[p].num = T[p << 1].num + T[(p << 1) | 1].num;
}
void updata(int pos , int p , int ad) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l == T[p].r && T[p].l == pos) {
        T[p].num = ad;
        return ;
    }
    if(mid >= pos) {
        updata(pos , p << 1 , ad);
    }
    else {
        updata(pos , (p << 1) | 1 , ad);
    }
    T[p].num = T[p << 1].num + T[(p << 1) | 1].num;
}
int queryr(int p , int l , int r) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l >= l && T[p].r <= r) {
        if(T[p].l == T[p].r) {
            if(T[p].num == 0) {
                return T[p].l;
            }
            else {
                return n + 1;
            }
        }
        if(T[p << 1].r - T[p << 1].l + 1 > T[p << 1].num) {
            return queryr(p << 1 , l , r);
        }
        else {
            return queryr((p << 1) | 1 , l , r);
        }
    }
    if(mid >= r) {
        return queryr(p << 1 , l , r);
    }
    else if(mid < l) {
        return queryr((p << 1) | 1 , l , r);
    }
    else {
        return min(queryr(p << 1 , l , mid) , queryr((p << 1) | 1 , mid + 1 , r));
    }
}
int queryl(int p , int l , int r) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l >= l && T[p].r <= r) {
        if(T[p].l == T[p].r) {
            if(T[p].num == 0) {
                return T[p].l;
            }
            else {
                return 0;
            }
        }
        if(T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1 > T[(p << 1) | 1].num) {
            return queryl((p << 1) | 1 , l , r);
        }
        else {
            return queryl(p << 1 , l , r);
        }
    }
    if(mid >= r) {
        return queryl(p << 1 , l , r);
    }
    else if(mid < l) {
        return queryl((p << 1) | 1 , l , r);
    }
    else {
        return max(queryl(p << 1 , l , mid) , queryl((p << 1) | 1 , mid + 1 , r));
    }
}
int query(int p , int pos) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l == T[p].r) {
        return T[p].num;
    }
    if(mid >= pos) {
        return query(p << 1 , pos);
    }
    else {
        return query((p << 1) | 1 , pos);
    }
}
int main() {
    while(~scanf("%d%d" , &n , &m)) {
        build(1 , n , 1);
        char cp[2];
        stack<int>ss;
        int mm;
        for(int i = 0 ; i < m ; i++) {
            scanf("%s" , cp);
            if(cp[0] == 'D') {
                scanf("%d" , &mm);
                updata(mm , 1 , 0);
                ss.push(mm);
            }
            if(cp[0] == 'Q') {
                scanf("%d" , &mm);
                int g = query(1 , mm);
                if(g == 0) {
                    printf("0\n");
                    continue;
                }
                int L = queryl(1 , 1 , mm);
                int R = queryr(1 , mm , n);
                printf("%d\n" , R - L - 1);
            }
            if(cp[0] == 'R') {
                if(!ss.empty()) {
                    int gl = ss.top();
                    ss.pop();
                    updata(gl , 1 , 1);
                }
            }
        }
    }
    return 0;
}
posted @ 2016-12-05 14:44  Gealo  阅读(199)  评论(0)    收藏  举报