(i) hdu1540 (区间合并)

Posted lsy263

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(i) hdu1540 (区间合并)相关的知识,希望对你有一定的参考价值。

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;

 

以上是关于(i) hdu1540 (区间合并)的主要内容,如果未能解决你的问题,请参考以下文章

Tunnel Warfare HDU - 1540 (区间合并)

HDU1540 Tunnel Warfare —— 线段树 区间合并

HDU 1540 Tunnel Warfare(线段树 区间合并)

HDU 1540 Tunnel Warfare(区间合并)线段树

hdu 1540(线段树区间合并)

HDU 1540 Tunnel Warfare 线段树区间合并