HDU 1540 Tunnel Warfare(线段树维护最大连续区间长度)

题目大意:

一段长为n的区间,m此操作,Q为查询x所在区间的最大长度,D为将X破坏(不连通),R为将最后一个破坏的点修复(连通)。

题解思路:

线段树,维护3个值。

1.区间前缀长度

2.区间后缀长度

3.区间里最长连续区间

用栈存储一下破坏的点,线段树的更新维护写在代码里;

10001111 前缀为1 后缀为4;。

维护前缀和后缀,是为了在归并和查询过程中维护连续区间长度。

对于 0 0 0 1 1   1 1 1 0 1在归并中连续区间长度应为lson的后缀+rson的前缀

在维护父节点前缀(后缀)时优先继承左孩子前缀(右孩子后缀),如果左孩子前缀(右孩子后缀)的长度等于区间长度应再加上右孩子前缀(左孩子后缀)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<algorithm>
//被模板题搞自闭的蒟蒻
#define lson rt<<1
#define rson rt<<1|1

const int maxn=1e5+10;

using namespace std;

struct node{
    int ls,rs,sum;
}tree[4*maxn];
//ls 前缀 rs 后缀 sum连续区间长度

int n,m;

void built(int l,int r,int rt)
{
    int mid=(r+l)/2,sum=r-l+1;
    tree[rt]=(node){sum,sum,sum};
    if(l==r)
        return ;
    built(l,mid,lson);
    built(mid+1,r,rson);
}

void updata(int l,int r,int rt,int aim,int val)
{
    if(l==r)
    {
        tree[rt].ls=tree[rt].rs=tree[rt].sum=val;
        return ;
    }
    int mid=(l+r)>>1;
    if(aim<=mid)
    {
        updata(l,mid,lson,aim,val);
    }
    if(aim>mid)
    {
        updata(mid+1,r,rson,aim,val);
    }
    tree[rt].ls=tree[lson].ls;//父节点继承左孩子的前缀
    tree[rt].rs=tree[rson].rs;

    if(tree[lson].ls==mid-l+1)//如果左孩子的前缀等于区间长度(左孩子满了)
        tree[rt].ls+=tree[rson].ls;//加上右孩子的前缀
    if(tree[rson].rs==r-mid)
        tree[rt].rs+=tree[lson].rs;

    tree[rt].sum=max(max(tree[lson].sum,tree[rson].sum),tree[lson].rs+tree[rson].ls);
    //父节点的sum为 左右孩子的最大值 与 左右孩子连起来的区间区最大值
    //            例如:110111 100111
}

int query(int l,int r,int rt,int aim)
{
    if(l==r||tree[rt].sum==0||tree[rt].sum==l-r+1)
    {//如果到了叶子节点或者区间值等于0或区间长度直接返回即可
        return tree[rt].sum;
    }
    int mid=(l+r)>>1;
    if(aim<=mid)
    {
        if(aim>=mid-tree[lson].rs+1)
        //如果查询点在左孩子的后缀中
        //查询左孩子的长度加上右孩子的前缀
        //例如    0 0 0 1 1   1 1 1 0 1
        //             x
            return query(l,mid,lson,aim)+tree[rson].ls;
        else
        //否则只查询左孩子
            return query(l,mid,lson,aim);
    }
    else
    {
        if(aim<=mid+tree[rson].ls)
        //(mid+1)+tree[rson]-1
        //同上
        //  1 1 1 0 1   1 1 1 0 1
        //              x
            return query(mid+1,r,rson,aim)+tree[lson].rs;
        else
            return query(mid+1,r,rson,aim);
    }
}

int main(){
    while(~scanf("%d%d",&n,&m))
    {
        built(1,n,1);
        stack<int>q;
        while(m--)
        {
            char s[5];
            int now;
            scanf("%s",s);
            if(s[0]=='R')
            {
                if(q.size())
                {
                    updata(1,n,1,q.top(),1);
                    q.pop();
                }
            }
            if(s[0]=='D')
            {
                scanf("%d",&now);
                q.push(now);
                updata(1,n,1,now,0);
            }
            if(s[0]=='Q')
            {
                scanf("%d",&now);
                printf("%d\n",query(1,n,1,now));
            }
        }
    }
    return 0;
}

 

posted @ 2019-01-24 16:59  Minun  阅读(216)  评论(0编辑  收藏  举报