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

题目链接

题意:

给定一个有$N$个车位的停车场(都在一条直线上),现在有有两种操作

$1.x $     要停连续的停$x$辆车,输出第一辆车停的位置(尽量靠前),不能就输出$0$;

$2.x,d$ 从x位置开始开走连续的$d$辆车。

思路:

一个线段树区间和问题,而且满足区间可加性,就要用到区间合并。

  1 /*
  2 *  Author: windystreet
  3 *  Date  : 2018-08-15 10:29:55
  4 *  Motto : Think twice, code once.
  5 */
  6 #include <stdio.h>
  7 #include <string.h>
  8 #include <algorithm>
  9 
 10 using namespace std;
 11 
 12 #define X first
 13 #define Y second
 14 #define eps  1e-5
 15 #define gcd __gcd
 16 #define pb push_back
 17 #define PI acos(-1.0)
 18 #define lowbit(x) (x)&(-x)
 19 #define bug printf("!!!!!\n");
 20 #define mem(x,y) memset(x,y,sizeof(x))
 21 
 22 typedef long long LL;
 23 typedef long double LD;
 24 typedef pair<int,int> pii;
 25 typedef unsigned long long uLL;
 26 
 27 const int maxn = 5e4+7;
 28 const int INF  = 1<<30;
 29 const int mod  = 1e9+7;
 30 
 31 struct Tree
 32 {
 33     int l,r,lazy;
 34     int ls,rs,ms;    // 区间前缀,后缀,最大值
 35 }tree[maxn<<2];
 36 void build(int rt,int l,int r){
 37     tree[rt].r = r;tree[rt].l = l;tree[rt].lazy = -1;
 38     if(l == r){
 39         tree[rt].ms = tree[rt].ls = tree[rt].rs = 1;return;
 40     }
 41     int mid = ( l + r ) >> 1;
 42     build(rt<<1,l,mid);
 43     build(rt<<1|1,mid+1,r);
 44     tree[rt].ms = tree[rt].ls = tree[rt].rs = tree[rt<<1].ms + tree[rt<<1|1].ms;
 45 }
 46 void pushdown(int rt){
 47     if(tree[rt].lazy!=-1){                                       // 下推标记
 48         int mid = (tree[rt].r + tree[rt].l )>>1;
 49         tree[rt<<1|1].lazy = tree[rt<<1].lazy = tree[rt].lazy;
 50         tree[rt<<1].ls = tree[rt<<1].rs = tree[rt<<1].ms = (mid - tree[rt].l+1)*tree[rt].lazy;
 51         tree[rt<<1|1].ls = tree[rt<<1|1].rs = tree[rt<<1|1].ms = (tree[rt].r -mid)*tree[rt].lazy;
 52         tree[rt].lazy = -1;
 53     }
 54 }
 55 void pushup(int rt){                                              // 向上更新
 56     tree[rt].ls = tree[rt<<1].ls;
 57     tree[rt].rs = tree[rt<<1|1].rs;
 58     if(tree[rt<<1].ls == (tree[rt<<1].r - tree[rt<<1].l + 1)){    // 区间合并
 59         tree[rt].ls += tree[rt<<1|1].ls;
 60     }
 61     if(tree[rt<<1|1].rs == (tree[rt<<1|1].r - tree[rt<<1|1].l + 1)){
 62         tree[rt].rs += tree[rt<<1].rs;
 63     }
 64     tree[rt].ms = max(max(tree[rt<<1|1].ms,tree[rt<<1].ms),tree[rt<<1].rs+tree[rt<<1|1].ls);
 65 }
 66 void update(int rt,int L,int R,int l,int r,int v){
 67     if(l<=L&&R<=r){
 68         tree[rt].ls = tree[rt].rs = tree[rt].ms = v*(R - L + 1);
 69         tree[rt].lazy = v;return;
 70     }
 71     pushdown(rt);
 72     int mid = ( L + R) >>1;
 73     if(l<=mid) update(rt<<1,L,mid,l,r,v);
 74     if(r>mid)  update(rt<<1|1,mid+1,R,l,r,v);
 75     pushup(rt);
 76 }
 77 int query(int rt,int L,int R,int v){    
 78     pushdown(rt);
 79     int mid = (L + R) >>1;
 80     if(tree[rt<<1].ms>=v){                                // 尽量靠前
 81         return query(rt<<1,L,mid,v);
 82     }else if(tree[rt<<1].rs + tree[rt<<1|1].ls>=v){
 83         return mid - tree[rt<<1].rs + 1;
 84     }else{
 85         return query(rt<<1|1,mid+1,R,v);
 86     }
 87 }
 88 
 89 void solve(){
 90     int n,m,op,x,y;
 91     while(scanf("%d%d",&n,&m)!=EOF){
 92         build(1,1,n);
 93         while(m--){
 94             scanf("%d",&op);
 95             if(op==1){
 96                 scanf("%d",&x);
 97                 if(tree[1].ms<x){
 98                     puts("0");
 99                 }else{
100                     int pos = query(1,1,n,x);
101                     printf("%d\n",pos);
102                     update(1,1,n,pos,pos+x-1,0);
103                 }
104                 
105             }else{
106                 scanf("%d%d",&x,&y);
107                 update(1,1,n,x,x+y-1,1);
108             }
109         }
110     }
111     
112     return;
113 }
114 
115 int main()
116 {
117  //   freopen("F:\\in.txt","r",stdin);
118 //    freopen("out.txt","w",stdout);
119 //    ios::sync_with_stdio(false);
120     int t = 1;
121     //scanf("%d",&t);
122     while(t--){
123     //    printf("Case %d: ",cas++);
124         solve();
125     }
126     return 0;
127 }

 

转载于:https://www.cnblogs.com/windystreet/p/9484563.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值