zoukankan      html  css  js  c++  java
  • UESTC 1227 & POJ 3667 Hotel

    非常细腻的线段树题目啊,后来还是有个细节写错了,查了一个晚上。。就不分析了。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <utility>
    #include <cstdlib>
    using namespace std;
    #define N 80011
    
    struct node
    {
        int ls,rs,ms;
        int pos;
        int mark;   // 0: unsure  1: all-empty  2: all-full
    }tree[4*N];
    
    int n,m;
    
    void build(int l,int r,int rt)
    {
        tree[rt].ls = tree[rt].rs = tree[rt].ms = r-l+1;
        tree[rt].pos = l;
        if(l == r)
        {
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
    }
    
    int if_all_empty(int l,int r,int rt)
    {
        if(tree[rt].ls == r-l+1)
            return 1;
        return 0;
    }
    
    void update(int l,int r,int rt)
    {
        if(!tree[rt].mark)   
            return;
        if(tree[rt].mark == 1)  //全空,则下传给左右子树
        {
            int len = r-l+1;
            tree[2*rt].ls = tree[2*rt].rs = tree[2*rt].ms = (len+1)/2;
            tree[2*rt].pos = l;
            tree[2*rt+1].ls = tree[2*rt+1].rs = tree[2*rt+1].ms = len/2;
            tree[2*rt+1].pos = (l+r)/2+1;
            tree[2*rt].mark = tree[2*rt+1].mark = 1;
        }
        else if(tree[rt].mark == 2)  //全满,则下传给左右子树
        {
            tree[2*rt].ls = tree[2*rt].rs = tree[2*rt].ms = 0;
            tree[2*rt].pos = l;
            tree[2*rt+1].ls = tree[2*rt+1].rs = tree[2*rt+1].ms = 0;
            tree[2*rt+1].pos = (l+r)/2+1;
            tree[2*rt].mark = tree[2*rt+1].mark = 2;
        }
        tree[rt].mark = 0;   // not "== 0"
    }
    
    int query(int l,int r,int dis,int rt)
    {
        update(l,r,rt);
        if(tree[rt].ms<dis)
            return 0;
        if(tree[rt].ms == dis)
            return tree[rt].pos;
        int mid = (l+r)/2;
        if(tree[2*rt].ms>=dis)
            return query(l,mid,dis,2*rt);
        if(tree[2*rt].rs + tree[2*rt+1].ls>=dis)
            return mid - tree[2*rt].rs + 1;
        return query(mid+1,r,dis,2*rt+1);
    }
    
    void in_out(int l,int r,int aa,int bb,int flag,int rt)   //flag == 1: insert   else  quit
    {
        if(aa>r||bb<l)
            return;
        if(aa<=l&&bb>=r)
        {
            if(flag == 1)   //如果当前要入住
            {
                tree[rt].ls = tree[rt].rs = tree[rt].ms = 0;
                tree[rt].pos = l;
                tree[rt].mark = 2;
            }
            else  //如果当前要退房
            {
                tree[rt].ls = tree[rt].rs = tree[rt].ms = r-l+1;
                tree[rt].pos = l;
                tree[rt].mark = 1;
            }
            return;
        }
        update(l,r,rt);
        int mid = (l+r)/2;
        in_out(l,mid,aa,bb,flag,2*rt);     
        in_out(mid+1,r,aa,bb,flag,2*rt+1);
    
        tree[rt].ls = tree[2*rt].ls;
        if(if_all_empty(l,mid,2*rt))
            tree[rt].ls += tree[2*rt+1].ls;
        tree[rt].rs = tree[2*rt+1].rs;
        if(if_all_empty(mid+1,r,2*rt+1))
            tree[rt].rs += tree[2*rt].rs;
    
        tree[rt].ms = max(tree[2*rt].rs+tree[2*rt+1].ls,max(tree[2*rt].ms,tree[2*rt+1].ms));
    
        if(tree[rt].ms == tree[2*rt].ms)   //如果当前区间最大空房数等于左子树最大空房数
            tree[rt].pos = tree[2*rt].pos;  //则起点置为左子树的起点
    
        else if(tree[rt].ms == tree[2*rt].rs + tree[2*rt+1].ls)  //同理
            tree[rt].pos = mid - tree[2*rt].rs + 1;
    
        else
            tree[rt].pos = tree[2*rt+1].pos;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(tree,0,sizeof(tree));
        build(1,n,1);
        int i,flag;
        int x,dis;
        for(i=0;i<m;i++)
        {
            scanf("%d",&flag);
            if(flag == 1)
            {
                scanf("%d",&dis);
                int ans = query(1,n,dis,1);
                printf("%d
    ",ans);
                if(ans)
                    in_out(1,n,ans,ans+dis-1,1,1);
            }
            else if(flag == 2)
            {
                scanf("%d%d",&x,&dis);
                in_out(1,n,x,x+dis-1,2,1);
            }
        }
        return 0;
    }
    View Code

    作者:whatbeg
    出处1:http://whatbeg.com/
    出处2:http://www.cnblogs.com/whatbeg/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    更多精彩文章抢先看?详见我的独立博客: whatbeg.com

  • 相关阅读:
    c# 基础
    摹客插件,自动识别画板大小!
    知道这10点,你才是真正会画线框图
    在线原型实例(可编辑):图片社交-InstagraAPP
    16 种原型设计工具及其使用场景
    微博APP在线原型实例(可编辑)
    5款前端切图工具大比拼:谁是最强切图神器
    你真的了解这4款协作设计吗
    nvm 安装及使用(npm版本管理工具)
    webpack入门四 安装vue,并打包
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3488318.html
Copyright © 2011-2022 走看看