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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540

这个题目是个区间合并的模板题,但是有一点不同的是分两步查询思路很清晰;

这里有一个博客写的不错,我就不再赘述了;链接:http://blog.csdn.net/xingyeyongheng/article/details/11619461

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define inf 1<<30
#define s(a,b) scanf("%d%d",&a,&b)
#define Clear(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=50015;
int n,m,a,b,ch;
int num[N];     //  该数组记录被损坏的村庄;
int ls[N<<2],rs[N<<2];  //  分别存左右端点起的最大长度;
void PushUp(int rt,int m)
{
    ls[rt]=ls[rt<<1];
    rs[rt]=rs[rt<<1|1];
    if(ls[rt]==m-(m>>1)) ls[rt]+=ls[rt<<1|1];   //  左儿子区间最大长度为整个区间,需要拼接右儿子区间左端点起的最长长度;
    if(rs[rt]==m>>1) rs[rt]+=rs[rt<<1];         //  右儿子区间最大长度为整个区间,同理;
}
void Build(int l,int r,int rt)
{
    ls[rt]=rs[rt]=r-l+1;    //  初始化为最长长度;
    if(l!=r){
        int mid=(l+r)>>1;
        Build(l,mid,rt<<1);
        Build(mid+1,r,rt<<1|1);
    }
}
void Updata(int p,int v,int l,int r,int rt)
{
    if(l==r){
        ls[rt]=v;
        rs[rt]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) Updata(p,v,l,mid,rt<<1);
    else Updata(p,v,mid+1,r,rt<<1|1);
    PushUp(rt,r-l+1);
}
int QueryL(int L,int R,int l,int r,int rt)  //  返回右边左区间最大长度;
{
    if(L<=l&&r<=R) return ls[rt];
    int mid=(l+r)>>1;
    if(R<=mid) return QueryL(L,R,l,mid,rt<<1);
    else if(L>mid) return QueryL(L,R,mid+1,r,rt<<1|1);
    else{
        int lans=QueryL(L,mid,l,mid,rt<<1);
        int rans=QueryL(mid+1,R,mid+1,r,rt<<1|1);
        if(lans==mid-L+1) return lans+rans;
        else return lans;
    }
}
int QueryR(int L,int R,int l,int r,int rt)  //  返回左边右区间最大长度;
{
    if(L<=l&&r<=R) return rs[rt];
    int mid=(l+r)>>1;
    if(R<=mid) return QueryR(L,R,l,mid,rt<<1);
    else if(L>mid) return QueryR(L,R,mid+1,r,rt<<1|1);
    else{
        int lans=QueryR(L,mid,l,mid,rt<<1);
        int rans=QueryR(mid+1,R,mid+1,r,rt<<1|1);
        if(rans==R-mid) return lans+rans;
        return rans;
    }
}
int main()
{
    //freopen("../../in.txt","r",stdin);
    //freopen("../../out.txt","w",stdout);
    while(~s(n,m)){
        Build(1,n,1);
        int top=0;
        while(m--){
            scanf(" %c",&ch);
            if(ch=='D'){
                scanf("%d",&a);
                num[top++]=a;
                Updata(a,0,1,n,1);
            }else if(ch=='R'&&top>0){   //  top>0说明还有被损坏的村庄;
                int a=num[--top];
                Updata(a,1,1,n,1);
            }else if(ch=='Q'){
                scanf("%d",&a);
                int ans=QueryL(a,n,1,n,1)+QueryR(1,a,1,n,1);
                printf("%d\n",ans>0?ans-1:0);
            }
        }
    }
    return 0;
}


 

 

你可能感兴趣的:(数据结构-线段树)