• POJ 3667 Hotel (线段树区间合并)


    题目链接:http://poj.org/problem?id=3667

    题目大意:一共有n个房间,初始时都是空的,现在有m个操作,操作有以下两种:

    1.1 d :询问是否有连续d个空的房间,若有则输出连续房间的起始编号,若无则输出0

    2.2 xi d:将第xi个房间至第xi+d-1个房间清空

    解题思路:线段树维护区间最大连续长度,tree[cur].lm代表以区间左端点为起点的连续段的长度 tree[cur].rm代表以区间右端点为终点的连续段的长度,tree[2*cur].rm+tree[2*cur+1].lm代表包含该区间中点的连续段的长度 这是个隐含值(中间连续段),则区间内最长连续段值不止要从左右子节点的最长连续段中择最大 还要考虑该区间的中间连续段即tree[cur].len=max(tree[2*cur].rm+tree[2*cur+1].lm,max(tree[2*cur].len,tree[2*cur+1].len));

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=50007;
    int n,m;
    struct node{
        int lm,rm,len,cov;
    }tree[maxn<<2];
    
    void pushup(int len,int rt){
        tree[rt].lm=tree[rt<<1].lm;
        if(tree[rt].lm==len-(len>>1)){
            tree[rt].lm+=tree[rt<<1|1].lm;
        }
        tree[rt].rm=tree[rt<<1|1].rm;
        if(tree[rt].rm==(len>>1)){
            tree[rt].rm+=tree[rt<<1].rm;
        }
        tree[rt].len=max(tree[rt<<1].rm+tree[rt<<1|1].lm,max(tree[rt<<1].len,tree[rt<<1|1].len));
    }
    void pushdown(int len,int rt){
        if(tree[rt].cov!=-1){
            tree[rt<<1].cov=tree[rt<<1|1].cov=tree[rt].cov;
            tree[rt<<1].lm=tree[rt<<1].rm=tree[rt<<1].len=tree[rt].cov?0:(len-(len>>1));
            tree[rt<<1|1].lm=tree[rt<<1|1].rm=tree[rt<<1|1].len=tree[rt].cov?0:(len>>1);
            tree[rt].cov=-1;
        }
    }
    void build(int l,int r,int rt){
        tree[rt].cov=-1;
        tree[rt].lm=tree[rt].rm=tree[rt].len=r-l+1;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    }
    void update(int L,int R,int val,int l,int r,int rt){
        if(L<=l&&R>=r){
            tree[rt].cov=val;
            tree[rt].lm=tree[rt].rm=tree[rt].len=val?0:(r-l+1);
            return;
        }
        int mid=(l+r)>>1;
        pushdown(r-l+1,rt);
        if(L<=mid) update(L,R,val,l,mid,rt<<1);
        if(R>mid) update(L,R,val,mid+1,r,rt<<1|1);
        pushup(r-l+1,rt);
    }
    int query(int w,int l,int r,int rt){
        if(l==r)return 1;
        pushdown(r-l+1,rt);
        int mid=(l+r)>>1;
        if(tree[rt<<1].len>=w) return query(w,l,mid,rt<<1);
        else if(tree[rt<<1].rm+tree[rt<<1|1].lm>=w) return mid-tree[rt<<1].rm+1;
        else return query(w,mid+1,r,rt<<1|1);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int op,x,cnt,ans;
            scanf("%d",&op);
            if(op==1){
                scanf("%d",&cnt);
                if(tree[1].len<cnt) ans=0;
                else ans=query(cnt,1,n,1);
                printf("%d
    ",ans);
                if(ans>0) 
                    update(ans,ans+cnt-1,1,1,n,1);
            }else{
                scanf("%d%d",&x,&cnt);
                update(x,x+cnt-1,0,1,n,1);
            }
        }
        return 0;
    }
  • 相关阅读:
    IE10 下兼容性问题
    前端面试题十九
    前端面试题十八
    前端面试题十七
    前端面试题十六
    前端面试题十五
    前端面试题十四
    前端面试题十三(兼容)
    前端面试题十二
    前端面试题十一
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/11673406.html
Copyright © 2020-2023  润新知