ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDOJ-1540(线段树+较复杂的单点修改和区间查询)

2019-09-02 21:02:58  阅读:269  来源: 互联网

标签:单点 1540 int mid 长度 区间 return id HDOJ


Tunnel Warfare

HDOJ-1540

  • 这题关于线段树的操作有一定的难度,需要较好的思维能力。
  • 关于题目的详细解答已经在代码中体现了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn=50004;
int n,m;
int llen[maxn<<2];//左端点起的最大长度
int rlen[maxn<<2];//右端点起的最大长度
void pushup(int id,int l,int r){
    int lc=id<<1;
    int rc=id<<1|1;
    int ch=r-l+1;//ch表示id(父亲)结点的覆盖长度
    llen[id]=llen[lc];//左端点起的最大长度等于左儿子左端点起的最大长度
    rlen[id]=rlen[rc];
    if(llen[id]==ch-(ch>>1))//如果左儿子最大长度为结点整个区间,那么父亲结点要加上右儿子左端点起的最大长度
        llen[id]+=llen[rc];
    if(rlen[id]==(ch>>1))   //如果右儿子最大长度为结点整个区间,那么父亲结点要加上左儿子右端点起的最大长度
        rlen[id]+=rlen[lc];
}
void build(int id,int l,int r){
    if(l==r){
        llen[id]=1;
        rlen[id]=1;
        return;
    }
    //长度全部初始化为结点覆盖的长度
    llen[id]=r-l+1;
    rlen[id]=r-l+1;
    int mid=(l+r)>>1;
    int lc=id<<1;int rc=id<<1|1;
    build(lc,l,mid);
    build(rc,mid+1,r);
}
void update(int id,int l,int r,int p,int v){
    if(l==r){
        llen[id]=v;
        rlen[id]=v;
        return;
    }
    int mid=(l+r)>>1;
    int lc=id<<1;
    int rc=id<<1|1;
    if(p<=mid){
        update(lc,l,mid,p,v);
    }else{
        update(rc,mid+1,r,p,v);
    }
    pushup(id,l,r);
}
int queryL(int id,int l,int r,int p,int q){//查询右边区间左端点起的最大长度
    if(p<=l&&q>=r){
        return llen[id];
    }
    int mid=(l+r)>>1;
    int lc=id<<1;
    int rc=id<<1|1;
    if(q<=mid){//表示待查询的区间完全在左边
        return queryL(lc,l,mid,p,q);
    }else if(p>mid){//表示待查询的区间完全在右边
        return queryL(rc,mid+1,r,p,q);
    }else{//mid在待查询区间之内
        int lans=queryL(lc,l,mid,p,mid);
        int rans=queryL(rc,mid+1,r,mid+1,q);
        if(lans==mid-p+1){//如果左区间最大长度为整个区间,这个时候才需要加上右边区间左端点起的最大长度
            return lans+rans;
        }else return lans;
        
    }
}
int queryR(int id,int l,int r,int p,int q){//查询右边区间左端点起的最大长度
    if(p<=l&&q>=r){
        return rlen[id];
    }
    int mid=(l+r)>>1;
    int lc=id<<1;
    int rc=id<<1|1;
    if(q<=mid){
        return queryR(lc,l,mid,p,q);
    }else if(p>mid){
        return queryR(rc,mid+1,r,p,q);
    }else{
        int lans=queryR(lc,l,mid,p,mid);
        int rans=queryR(rc,mid+1,r,mid+1,q);
        if(rans==q-mid){//同理,如果有区间的最大长度为整个区间,这个时候才需要加上左边区间右端点起的最大长度
            return lans+rans;
        }else return rans;
    }
}
int main(){
    while(cin>>n>>m){
        vector<int> v;
        build(1,1,n);
        for(int i=0;i<m;i++){
            char c;int x;
            cin>>c;
            if(c=='D'){//update
                cin>>x;
                v.push_back(x);
                update(1,1,n,x,0);
            }else if(c=='Q'){//query
                cin>>x;
                int ans=queryL(1,1,n,x,n)+queryR(1,1,n,1,x);//相当于查询左边区间右端点起最大长度加上右边区间左端点起最大长度
                cout<<(ans>0?ans-1:0)<<endl;
            }else if(c=='R'&&v.size()>0){//update
                x=v[v.size()-1];
                v.pop_back();
                update(1,1,n,x,1);
            }
        }
    }
    return 0;
}

标签:单点,1540,int,mid,长度,区间,return,id,HDOJ
来源: https://www.cnblogs.com/GarrettWale/p/11448965.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有