• [题解](线段树最大连续子段和)POJ_3667_Hotel


    题意:1.求一个最靠左的长x的区间全部为0,并修改为1,输出这个区间的左端点

    2.修改一个区间为0

    实际上是维护最大连续子段和,原来也写过

    大概需要维护一个左/右最大子段和,当前这段最大子段长,再维护一个lazytag

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mid (l+r>>1)
    #define ls x<<1
    #define rs x<<1|1
    using namespace std;
    const int maxn=50009;
    struct node{
        int l,r,mx,tg;//0全空,1全满,-1没有
    }t[maxn<<2];
    //inline void upd(int x,int l,int r){
    //    t[x].l=t[ls].l;
    //    t[x].r=t[rs].r;
    ////    if(t[ls].l==mid-l+1)t[x].l+=t[rs].l;
    ////    if(t[rs].r==r-mid)t[x].r+=t[ls].r;
    //    if(t[ls].l==(r-l+1-(r-l+1)/2))t[x].l+=t[rs].l;
    //    if(t[rs].r==(r-l+1)/2)t[x].r+=t[ls].r;
    //    t[x].mx=max(max(t[ls].mx,t[rs].mx),t[ls].r+t[rs].l);
    //}
    //inline void pushdown(int x,int l,int r){
    //    if(t[x].tg!=-1){
    //        t[ls].tg=t[rs].tg=t[x].tg;
    //        t[ls].l=t[ls].r=t[ls].mx=(r-l+1-(r-l+1)/2)*t[x].tg;
    //        t[rs].l=t[rs].r=t[rs].mx=(r-l+1)/2*t[x].tg;
    ////        if(t[x].tg==0){
    ////            t[ls].l=t[ls].r=t[ls].mx=mid-l+1;
    ////            t[rs].l=t[rs].r=t[rs].mx=r-mid;    
    ////        }
    ////        else{
    ////            t[ls].l=t[ls].r=t[ls].mx=0;
    ////            t[rs].l=t[rs].r=t[rs].mx=0;
    ////        }
    //        t[x].tg=-1;
    //    }
    //}
    inline void pushdown(int x,int len){
        if(t[x].tg!=-1){
            t[ls].tg=t[rs].tg=t[x].tg;
            t[ls].mx=t[ls].l=t[ls].r=t[x].tg*(len-(len>>1));
            t[rs].mx=t[rs].l=t[rs].r=t[x].tg*(len>>1);
            t[x].tg=-1;
        }
    }
    inline void upd(int x,int len){
        t[x].l=t[ls].l;
        t[x].r=t[rs].r;
        if(t[x].l==len-(len>>1))t[x].l+=t[rs].l;
        if(t[x].r==(len>>1))t[x].r+=t[ls].r;
        t[x].mx=max(max(t[ls].mx,t[rs].mx),t[ls].r+t[rs].l);
    }
    void build(int x,int l,int r){
        t[x].l=t[x].r=t[x].mx=r-l+1;t[x].tg=-1;
        if(l==r)return;
        build(ls,l,mid);build(rs,mid+1,r);
    }
    void change(int x,int l,int r,int L,int R,int k){
        if(L<=l && r<=R){
            t[x].l=t[x].r=t[x].mx= k==0?0:r-l+1;
            t[x].tg=k;
            return;
        }
    //    pushdown(x,l,r);
        pushdown(x,r-l+1);
        if(L<=mid)change(ls,l,mid,L,R,k);
        if(R>mid)change(rs,mid+1,r,L,R,k);
    //    upd(x,l,r);
        upd(x,r-l+1);
    }
    int query(int x,int l,int r,int k){
        if(l==r)return 1;
    //    pushdown(x,l,r);
        pushdown(x,r-l+1);
        if(t[ls].mx>=k)return query(ls,l,mid,k);
        else if(t[ls].r+t[rs].l>=k)return mid-t[ls].r+1;
        else return query(rs,mid+1,r,k);
    }
    int n,m;
    int main(){
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1,op,x,y;i<=m;i++){
            scanf("%d",&op);
            if(op==1){
                scanf("%d",&x);
                if(t[1].mx<x)printf("0
    ");
                else{
                    int pos=query(1,1,n,x);
                    printf("%d
    ",pos);
                    change(1,1,n,pos,pos+x-1,0);
                }
            }
            else{
                scanf("%d%d",&x,&y);
                change(1,1,n,x,x+y-1,1);
            }
        }
    }
  • 相关阅读:
    wpf 样式
    珠宝软件操作手册
    解决redis连接错误:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to...
    Jquery页面中添加键盘按键事件,如ESC事件
    .NET中ToString()的用法
    Springboot-shiro-redis实现登录认证和权限管理
    redis读书笔记
    mongoDB工具类以及测试类【java】
    自己的mongodb的CRUD封装
    这两天学的线程池归纳
  • 原文地址:https://www.cnblogs.com/superminivan/p/11025449.html
Copyright © 2020-2023  润新知