(i) hdu1540 (区间合并) (线段树) (h) poj3667 (区间合并)

hdu 1540  Tunnel Warfare

如在阅读本文时遇到不懂的部分,请在评论区询问,或跳转 线段树总介绍

推荐先阅读 (线段树) (h) poj3667 (区间合并) 以获得线段树区间合并的一些知识

本题与上题(poj3667)基本相同,但要注意询问部分要求的是包含x的0区间长度

query (看看代码,倒也直观,很容易理解)

int query(int rt,int l,int r,int x){
    if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1)return MaxiLen[rt];
    //找到x ||含x的区间全是0 || 含x的区间全是1
  //自己看看分别会返回什么...MaxiLen维护区间内最长的0
int mid=l+r>>1; if(x<=mid){ if(x>=mid-last[LS]+1)return last[LS]+pre[RS]; //夹中间 else return query(LS,l,mid,x); //LS }else{ if(x<=mid+pre[RS])return last[LS]+pre[RS]; //夹中间 else return query(RS,mid+1,r,x); //RS } }

左右去找x十分普通,重点是夹在中间的情况,要分左右区间的前驱后继来看;以及整个区间的特殊情况判定 if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1) 这三种可以合并起来写

代码

/*i.hdu1540*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
const int N=2e6+3;
int STK[N],HEAD=0;int n,m;
int pre[N<<2],last[N<<2],MaxiLen[N<<2];
#define LS (rt<<1)
#define RS (LS|1)

void build(int rt,int l,int r){
    pre[rt]=last[rt]=MaxiLen[rt]=r-l+1;
    if(l==r)return;
    int mid=l+r>>1;
    build(LS,l,mid);
    build(RS,mid+1,r);
}
void pushup(int rt,int l,int r){
    MaxiLen[rt]=max(max(MaxiLen[LS],MaxiLen[RS]),pre[RS]+last[LS]);
    int mid=l+r>>1;
    if(pre[LS]==mid-l+1)pre[rt]=mid-l+1+pre[RS];
    else pre[rt]=pre[LS];
    if(last[RS]==r-mid)last[rt]=r-mid+last[LS];
    else last[rt]=last[RS];
    return;
}
void update(int rt,int l,int r,int x,int p){
    if(l==r){pre[rt]=last[rt]=MaxiLen[rt]=p;return;}
    int mid=l+r>>1;
    if(x<=mid)update(LS,l,mid,x,p);
    else update(RS,mid+1,r,x,p);
    pushup(rt,l,r);
}
int query(int rt,int l,int r,int x){
    if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1)return MaxiLen[rt];
    //找到x ||含x的区间全是0 || 含x的区间全是1
    int mid=l+r>>1;
    if(x<=mid){
        if(x>=mid-last[LS]+1)return last[LS]+pre[RS]; //夹中间
        else return query(LS,l,mid,x);                 //LS
    }else{
        if(x<=mid+pre[RS])return last[LS]+pre[RS];     //夹中间
        else return query(RS,mid+1,r,x);               //RS
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        build(1,1,n);
        char c=getchar();int x;
        while(m--){
            c=getchar();
            if(c=='D'){
                scanf("%d",&x);
                update(1,1,n,x,0);
                STK[++HEAD]=x;
            }
            else if(c=='Q'){
                scanf("%d",&x);
                printf("%d\n",query(1,1,n,x));
            }
            else update(1,1,n,STK[HEAD--],1);
            c=getchar();
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lsy263/p/11229113.html