ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

酒店

2021-05-29 18:56:13  阅读:202  来源: 互联网

标签:酒店 sum rmax ret lmax other now


题目描述

A城市有个超级大酒店,住房部只有一层,只向南,但房间有N个(编号1, 2 .. N)。刚开始所有房间都是空的,但酒店肯定会有人来住宿,有些房间就要被入住。但客人经常会问一个问题,最长连续的空房间是多少,因为客人想连续的住在一起。于是,有下列三个操作:

1 a b:表示从房间a开始连续b个房间,将被入住(不管有没有人已经入住)

2 a b:表示从房间a开始连续b个房间,将清空入住(不管有没有人入住)

3:表示询问当前最长连续的空房间是多少?

对于3的询问,输出相应答案。

 

输入

首先输入N和P,  N如问题描述,P表示有多少个操作

然后输入P个操作

 

输出

对于第三种操作,输出相应答案

 

样例输入

12 10
3
1 2 3
1 9 4
3
2 2 1
3
2 9 2
3
2 3 2
3

样例输出

12
4
4
6
10

提示

 

【数据规模和约定】


3<=N<=16,000


3<=P<=200,000

 

 

首先,大家都能看出来,这是一道线段树的题。

那么除了常规的区记录间左右端点的数组,lazy数组,还要有一个数组sum[],表示所在区间内最长连续的空房间数。但是这并不够,在区间合并的时候很容易证明sum[now] = sum[now << 1] + sum[now << 1 | 1]是错的,这里不解释。

所以对于每一个区间,还要维护两个值:一个是从左端点开始最长连续空房间数lmax,另一个是从右端点开始最长连续空房间数rmax,举个栗子:

对于区间[1, 14]:

      1 2 3 4 5 6 7 8 9 10 11 12 13 14 

               # # #                          #            

'#' 为已经入住的个房间

此时sum[now] = 6, lmax = 3, rmax = 1.

那么对于维护sum[now],就可以得出

    sum[now] = max(sum[now << 1], sum[now << 1 | 1], rmax[now << 1] + lmax[now << 1 | 1])

也就是说要考虑连个子区间的空房间刚好连在一块的情况。

 

接下来就是想办法维护lmax[now]和rmax[now].

这个也不难(但我还是智障了debug了好长时间),想清楚了就行了。

拿lmax[now]举例,只要lmax[now << 1]是整个区间的长度的话,即now << 1整个区间都空,那么lmax[now] = lmax[now << 1] + lmax[now << 1 | 1],否则lmax[now] = lmax[now << 1].

 

rmax[now]同理。

 

最后想提一下lazy标记,和平时写的稍有些不同,不是累加的关系,而是将lazy[now]直接覆盖到lazy[now << 1]和lazy[now << 1 | 1]。因为对于一个房间只可能有入住和不入住两种情况,而这两种情况互不影响(题中描述如此:“不管有没有人已经入住”)。

 

所以更新的函数就写出来了。

更新,以及pushdown

 1 void pushdown(int now) 2 { 3     if(!a[now].lazy) return; 4     a[now << 1].lazy = a[now << 1 | 1].lazy = a[now].lazy; 5     a[now].lazy = 0; 6     if(a[now].lazy == 2)        //清空入住  7     { 8         a[now << 1].lmax = a[now << 1].rmax = a[now << 1].sum = a[now << 1].len; 9         a[now << 1 | 1].lmax = a[now << 1 | 1].rmax = a[now << 1 | 1].sum = a[now << 1 | 1].len;10     }11     else12     {13         a[now << 1].lmax = a[now << 1].rmax = a[now << 1].sum = 0;14         a[now << 1 | 1].lmax = a[now << 1 | 1].rmax = a[now << 1 | 1].sum = 0;15     }16 }17 void update(int L, int R, int now, int d)18 {19     if(L == a[now].l && R == a[now].r)20     {21         if(d == 2) a[now].lmax = a[now].rmax = a[now].sum = R - L + 1;22         else a[now].lmax = a[now].rmax = a[now].sum = 0;23         a[now].lazy = d; return;        //直接覆盖lazy 24     }25     pushdown(now);26     int mid = (a[now].r + a[now].l) >> 1;27     if(R <= mid) update(L, R, now << 1, d);28     else if(L > mid) update(L, R, now << 1 | 1, d);29     else {update(L, mid, now << 1, d); update(mid + 1, R, now << 1 | 1, d);}30     a[now] = a[now << 1] + a[now << 1 | 1];            //因为用了结构体,所以这里重载了一下加号。 31 }

啊对了,补一下定义的结构体和重载运算符

struct Tree
{    int l, r, lazy, len;        //len:区间长度 
    int sum, lmax, rmax;    /*其实这种封装也有一定的弊端,因为在重载加号的时候,返回的是一个新的结构体,
    所以必须对他的所有成员都赋上相应的值,否则会出错,具体看下方注释 */ 
    Tree operator + (const Tree& other)const
    {
        Tree ret;
        ret.sum = max(max(sum, other.sum), rmax + other.lmax);
        ret.l = l; ret.r = other.r;
        ret.len = ret.r - ret.l + 1;        //这就是容易疏忽的一点,我当时就忘了给len赋值,debug了1个多小时 
        if(lmax == len) ret.lmax = lmax + other.lmax;    //分情况维护lmax,rmax 
        else ret.lmax = lmax;        if(other.rmax == other.len) ret.rmax = other.rmax + rmax;        else ret.rmax = other.rmax;
        ret.lazy = 0;    //因为这条语句是在pushdown之后执行的,所以lazy已经被清空了 
        return ret;    
        /*如此看来,结构体里就应该有sum,lmax,rmax,因为其他都是不变的,或是在pushup操作里不需要的
        这么做也是尽量减少运算次数进行常数优化,但最重要的是,这样显得思维清晰,代码简练*/ 
    }
}a[maxn << 2];

 对于查询,只用返回a[1].sum了,因为是全局查询。

 

完整版代码

  1 #include  2 #include  3 #include  4 #include  5 #include  6 #include  7 using namespace std;  8 #define enter printf("\n")  9 #define space printf(" ") 10 typedef long long ll; 11 const int INF = 0x3f3f3f3f; 12 const int maxn = 2e4 + 5; 13 inline ll read() 14 { 15     ll ans = 0; 16     char ch = getchar(), last = ' '; 17     while(!isdigit(ch)) {last = ch; ch = getchar();} 18     while(isdigit(ch)) 19     { 20         ans = ans * 10 + ch - '0'; ch = getchar();    
 21     } 22     if(last == '-') ans = -ans; 23     return ans; 24 } 25 inline void write(ll x) 26 { 27     if(x < 0) x = -x, putchar('-'); 28     if(x >= 10) write(x / 10); 29     putchar('0' + x % 10); 30 } 31  32 int n, p; 33  34 struct Tree 35 { 36     int l, r, lazy, len;        
 37     int sum, lmax, rmax; 38     Tree operator + (const Tree& other)const 39     { 40         Tree ret; 41         ret.sum = max(max(sum, other.sum), rmax + other.lmax); 42         ret.l = l; ret.r = other.r; 43         ret.len = ret.r - ret.l + 1;        
 44         if(lmax == len) ret.lmax = lmax + other.lmax;    
 45         else ret.lmax = lmax; 46         if(other.rmax == other.len) ret.rmax = other.rmax + rmax; 47         else ret.rmax = other.rmax; 48         ret.lazy = 0;    
 49         return ret;    
 50     } 51 }a[maxn << 2]; 52 void build(int L, int R, int now) 53 { 54     a[now].l = L; a[now].r = R; 55     a[now].sum = a[now].lmax = a[now].rmax = a[now].len = R - L + 1; 56     a[now].lazy = 0; 57     if(L == R) return;    
 58     int mid = (L + R) >> 1; 59     build(L, mid, now << 1); 60     build(mid + 1, R, now << 1 | 1); 61 } 62 void pushdown(int now) 63 { 64     if(!a[now].lazy) return; 65     a[now << 1].lazy = a[now << 1 | 1].lazy = a[now].lazy; 66     a[now].lazy = 0; 67     if(a[now].lazy == 2)        
 68     { 69         a[now << 1].lmax = a[now << 1].rmax = a[now << 1].sum = a[now << 1].len; 70         a[now << 1 | 1].lmax = a[now << 1 | 1].rmax = a[now << 1 | 1].sum = a[now << 1 | 1].len; 71     } 72     else 73     { 74         a[now << 1].lmax = a[now << 1].rmax = a[now << 1].sum = 0; 75         a[now << 1 | 1].lmax = a[now << 1 | 1].rmax = a[now << 1 | 1].sum = 0; 76     } 77 } 78 void update(int L, int R, int now, int d) 79 { 80     if(L == a[now].l && R == a[now].r) 81     { 82         if(d == 2) a[now].lmax = a[now].rmax = a[now].sum = a[now].len; 83         else a[now].lmax = a[now].rmax = a[now].sum = 0; 84         a[now].lazy = d; return;        
 85     } 86     pushdown(now); 87     int mid = (a[now].r + a[now].l) >> 1; 88     if(R <= mid) update(L, R, now << 1, d); 89     else if(L > mid) update(L, R, now << 1 | 1, d); 90     else {update(L, mid, now << 1, d); update(mid + 1, R, now << 1 | 1, d);} 91     a[now] = a[now << 1] + a[now << 1 | 1];             
 92 } 93  94 int main() 95 { 96     n = read(); p = read(); 97     build(1, n, 1); 98     for(int i = 1; i <= p; ++i) 99     {100         int d = read();101         if(d == 3) {write(a[1].sum); enter;} 
102         else103         {104             int L = read(), add = read();105             update(L, L + add - 1, 1, d);106         }107     }108     return 0;109 }

 

 

标签:酒店,sum,rmax,ret,lmax,other,now
来源: https://blog.51cto.com/u_15234622/2830828

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有