Tunnel Warfare HDU - 1540 线段树维护区间长度

在抗日战争期间,华北平原广大地区进行了大规模的隧道战。 一般来说,通过隧道连接的村庄排成一列。 除了两端,每个村庄都与两个相邻的村庄直接相连。
入侵者经常对一些村庄发动袭击并摧毁其中的部分隧道。 八路军指挥官要求最新的隧道和村庄连接状态。 如果某些村庄严重隔离,必须立即恢复连接!
Input
输入的第一行包含两个正整数n和m(n,m≤50,000),表示村庄和事件的数量。 接下来的m行中的每一行描述一个事件。
以下所示的不同格式描述了三种不同的事件:
D x:第x个村庄被毁。
Q x:指挥官询问第x个村庄与其直接或间接相关的村庄数量。
R:最后毁坏的村庄被重建了。
Output
按顺序输出每个指挥官询问的答案。
Sample Input
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
Sample Output
1
0
2
4

线段树维护一个最长的数字的区间,WA点:一个点可以反复被删除

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>

using namespace std;
char ch[10];
struct node
{
    int l, r;
} tree[50010 * 4];

void build(int x, int y, int z)
{
    tree[z].l = tree[z].r = y - x + 1;
    if (x == y)
        return;
    int mid = (x + y) / 2;
    build(x, mid, z << 1);
    build(mid + 1, y, z << 1 | 1);
}

void getsum(int l, int x, int y, int z, int num)
{
    if (l < x || l > y)
        return;
    if (x == y)
    {
        tree[z].l = tree[z].r = num;
        return;
    }
    int mid = (x + y) / 2;
    getsum(l, x, mid, z << 1, num);
    getsum(l, mid + 1, y, z << 1 | 1, num);
    tree[z].l = tree[z << 1].l;
    tree[z].r = tree[z << 1 | 1].r;
    if (tree[z].l == mid - x + 1)
        tree[z].l += tree[z << 1 | 1].l;
    if (tree[z].r == y - mid)
        tree[z].r += tree[z << 1].r;
}

int query(int l, int x, int y, int z)
{
    int mid = (x + y) / 2;
    if (x == y || tree[z].l == y - x + 1)
        return tree[z].l;
    if (l < mid + 1 - tree[z << 1].r)
        return query(l, x, mid, z << 1);
    if (l > mid + tree[z << 1 | 1].l)
        return query(l, mid + 1, y, z << 1 | 1);
    return tree[z << 1].r + tree[z << 1 | 1].l;
}

int n,m,k;

int main()
{
    while (~scanf("%d %d", &n, &m))
    {
        build(1, n, 1);
        stack<int>sta;
        while (m--){
            cin>>ch;
            if (ch[0] == 'D'){
                scanf("%d", &k);
                sta.push(k);
                getsum(k, 1, n, 1, 0);
            }
            else if (ch[0] == 'R'){
                k = sta.top();
                sta.pop();
                getsum(k, 1, n, 1, 1);
            }
            else{
                cin>>k;
                cout<<query(k, 1, n, 1)<<endl;
            }
        }
    }
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值