zoukankan      html  css  js  c++  java
  • 线段树 poj 3667

    1-n线段 m个操作

    1  a

    是否可找到连续a个空位子 有输出最左边(然后使这一段被占)没有0

    2 a ,b

    a~b区间变成未使用

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    #define MAXN   50010
    
    struct node
    {
        int l,r,lsum,rsum,msum,la;
    }x[MAXN<<3];
    void Build(int l,int r,int a)
    {
        x[a].l=l;
        x[a].r=r;
        x[a].lsum=x[a].rsum=x[a].msum=r-l+1;
        x[a].la=-1;
        if(l==r)
            return ;
        int mid=(l+r)>>1;
        Build(l,mid,a<<1);
        Build(mid+1,r,a<<1|1);
    }
    void push_down(int a)
    {
        int ll=x[a<<1].r-x[a<<1].l+1;
        int rr=x[a<<1|1].r-x[a<<1|1].l+1;
        x[a<<1].la=x[a<<1|1].la=x[a].la;
        x[a<<1].rsum=x[a<<1].lsum=x[a<<1].msum=x[a].la?0:ll;
        x[a<<1|1].rsum=x[a<<1|1].lsum=x[a<<1|1].msum=x[a].la?0:rr;
        x[a].la=-1;
    }
    void push_up(int a)
    {
        int ll=x[a<<1].r-x[a<<1].l+1;
        int rr=x[a<<1|1].r-x[a<<1|1].l+1;
        x[a].lsum=x[a<<1].lsum;
        if(x[a].lsum==ll)//区间合并
            x[a].lsum+=x[a<<1|1].lsum;
        x[a].rsum=x[a<<1|1].rsum;
        if(x[a].rsum==rr)
            x[a].rsum+=x[a<<1].rsum;
        x[a].msum=max(max(x[a<<1].msum,x[a<<1|1].msum),x[a<<1].rsum+x[a<<1|1].lsum);
    }
    
    void update(int l,int r,int a1,int b1,int w,int a)
    {
        if(a1<=l&&r<=b1)
        {
            x[a].lsum=x[a].rsum=x[a].msum=w?0:(r-l+1);
            x[a].la=w;
            return ;
        }
        int mid=(l+r)>>1;
        if(x[a].la!=-1)
            push_down(a);
        if(a1<=mid)
            update(l,mid,a1,b1,w,a<<1);
        if(b1>mid)
            update(mid+1,r,a1,b1,w,a<<1|1);
        push_up(a);
    }
    int Ques(int l,int r,int w,int a)
    {
        if(l==r)
            return l;
        if(x[a].la!=-1)
            push_down(a);
        int mid=(l+r)>>1;
        if(x[a<<1].msum>=w)//左孩子最大连续区间够了
            return Ques(l,mid,w,a<<1);
        else if(x[a<<1].rsum+x[a<<1|1].lsum>=w)//中间连续够了
            return mid-x[a<<1].rsum+1;
        return Ques(mid+1,r,w,a<<1|1); //右边
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        Build(1,n,1);
        while(m--)
        {
            int op,a,b;
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d",&a);
                if(x[1].msum<a)//最大的
                    printf("0
    ");
                else
                {
                    int p=Ques(1,n,a,1);
                    printf("%d
    ",p);
                    update(1,n,p,p+a-1,1,1);//变成使用
                }
            }
            else
            {
                scanf("%d%d",&a,&b);
                update(1,n,a,a+b-1,0,1);//变成未使用
            }
        }
        return 0;
    }
  • 相关阅读:
    ubuntu 搜索文件方法(find命令)
    tomcat ip访问
    Linux下tomcat 的启动 关闭 kill
    Hibernate 之 使用
    tar 用法
    ubuntu下配置django+apache+mysql+mod_python+Python
    Windows Mobile Ping 命令实现(转)
    C#异步方法调用(四大方法详解)
    HTML基础(一):HTML简介
    windows2003系统的iis不能下载exe文件
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6210700.html
Copyright © 2011-2022 走看看