HDU 1540 Tunnel Warfare

题目大意

给定一个区间,有3种操作方式,操作为D是,摧毁a点,操作为Q时,询问包括a在内相怜的结点数,操作为R是,重新建立最近一次摧毁a点。

题目分析

本题为线段树区间合并,因为必须更新到叶子节点,所以不需要设置延迟标记,直接更新到叶子节点就可以了。

#include 
#include 
#include 
using namespace std;
const int maxn = 50005;
#define mid (L+R)/2
#define lson o<<1, L, mid
#define rson o<<1|1, mid+1, R

int que[maxn];
int lsum[maxn<<2],rsum[maxn<<2];

void pushup(int o,int m)
{
    lsum[o] = lsum[o<<1], rsum[o] = rsum[o<<1|1];
    if(lsum[o] >= m - (m>>1))
        lsum[o] += lsum[o<<1|1];
    if(rsum[o] >= (m>>1))
        rsum[o] += rsum[o<<1];
}

void build(int o,int L,int R)
{
    lsum[o] = rsum[o] = R-L+1;
    if(L == R) return ;
    build(lson);
    build(rson);
}

void update(int o,int L,int R,int p,int c)
{
    if(L == R)
    {
        lsum[o] = rsum[o] = c;
        return ;
    }
    if(p <= mid) update(lson, p, c);
    else update(rson, p, c);
    pushup(o, R-L+1);
}

int query(int o,int L,int R,int p)
{
    if(L == R) return 0;
    if(mid-rsum[o<<1]+1 <= p && mid+lsum[o<<1|1] >= p)
        return rsum[o<<1] + lsum[o<<1|1];
    if(p <= mid) return query(lson, p);
    else return query(rson, p);
}

int main()
{
    int n,m;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        char op;
        int a,top = 0;
        build(1, 1, n);
        while(m--)
        {
            cin >> op;
            if(op == 'D'){
                scanf("%d", &a);
                update(1, 1, n, a, 0);
                que[++top] = a;
            }
            else if(op == 'Q'){
                scanf("%d", &a);
                printf("%d\n",query(1, 1, n, a));
            }
            else
                if(top) update(1, 1, n, que[top--], 1);
        }
    }
    return 0;
}

你可能感兴趣的:(ACM_HDU,数据结构_线段树)