HDU 1540 Tunnel Warfare(单点更新,区间合并)

题目链接:
HDU 1540 Tunnel Warfare
吐槽:

if(goal<=segtree[rson(cur)].left+segtree[rson(cur)].left_max-1)

这一行代码起初少写了一个 "1" ,WA到吐血!!!!!!

//4012K 327MS
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define lson(x) (x<<1)
#define rson(x) ((x<<1)|1)
using namespace std;
const int maxn=50010;
int n,m,x,top;
int des[maxn];
char s[5];

struct SegTree{
    int left,right,len;//len是区间长度
    int left_max,right_max;
    //left_max和right_max分别是左右端点在该区间的最大连通
}segtree[maxn<<2];

inline void push_up(int cur)
{
    segtree[cur].left_max=segtree[lson(cur)].left_max;//父区间的左端最大连通等于左儿子的左端最大连通
    if(segtree[cur].left_max==segtree[lson(cur)].len){//左儿子的左端点将左儿子区间完全连通
        segtree[cur].left_max+=segtree[rson(cur)].left_max;//那么父区间的左端最大连通需要加上右儿子的左端最大连通
    }
    //同理
    segtree[cur].right_max=segtree[rson(cur)].right_max;
    if(segtree[cur].right_max==segtree[rson(cur)].len){
        segtree[cur].right_max+=segtree[lson(cur)].right_max;
    }
    return;
}

inline void build(int left,int right,int cur)
{
    segtree[cur].left=left;
    segtree[cur].right=right;
    segtree[cur].len=segtree[cur].left_max=segtree[cur].right_max=right-left+1;
    if(left==right) return;
    int mid=(left+right)>>1;
    build(left,mid,lson(cur));
    build(mid+1,right,rson(cur));
}

inline int query(int goal,int cur)
{
    int left=segtree[cur].left;
    int right=segtree[cur].right;
    if(goal==left) {
        return segtree[cur].left_max;
    }else if(goal==right){
        return segtree[cur].right_max;
    }
    int mid=(left+right)>>1;
    if(goal<=mid){//goal在左儿子区间
        if(goal>=segtree[lson(cur)].right-segtree[lson(cur)].right_max+1) 
            //在左儿子的右端最大连通里,还应加上右儿子的左端最大连通
            return segtree[lson(cur)].right_max+segtree[rson(cur)].left_max;
        else return query(goal,lson(cur));
    }else {//goal在右儿子区间
        if(goal<=segtree[rson(cur)].left+segtree[rson(cur)].left_max-1) 
            return segtree[lson(cur)].right_max+segtree[rson(cur)].left_max;
        else return query(goal,rson(cur));
    }
}

inline void update(int goal,int flag,int cur)
{
    int left=segtree[cur].left;
    int right=segtree[cur].right;
    if(left==right){
        segtree[cur].left_max=segtree[cur].right_max=flag;
        return;
    }
    int mid=(left+right)>>1;
    if(goal<=mid) update(goal,flag,lson(cur));
    else update(goal,flag,rson(cur));
    push_up(cur);
}

int main()
{
    //freopen("hdu1540in.txt","r",stdin);
    //freopen("hdu1540out.txt","w",stdout);
    while(~scanf("%d%d",&n,&m)){
        build(1,n,1);
        top=-1;
        while(m--){
            scanf("%s",s);
            if(s[0]=='D'){        //破坏
                scanf("%d",&x);
                des[++top]=x;
                update(x,0,1);
            }else if(s[0]=='R'){  //修复
                update(des[top--],1,1);
            }else{                //查询
                scanf("%d",&x);
                printf("%d\n",query(x,1));
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值