poj 1823 Hotel

http://poj.org/problem?id=1823

  这是一道线段树的题,很久以前就听说它很经典!这是【成段更新,全段询问】的线段树。

  题目要求的是更新指定区间,然后询问全部区间中连续区间的最大值。这题的时限比较紧,最好是用G++来做,C++我的代码超时了。。。。囧!

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cassert>
  5 
  6 using namespace std;
  7 
  8 #define lson l, m, rt << 1
  9 #define rson m + 1, r, rt << 1 | 1
 10 
 11 const int maxn = 16001;
 12 struct Hotel {
 13     int mx;
 14     int l, r;
 15 
 16     Hotel(int _set = 0): mx(_set), l(_set), r(_set) {}
 17 };
 18 Hotel seg[maxn << 2];
 19 int late[maxn << 2];
 20 
 21 void scan(int &a){
 22     char ch;
 23 
 24     while ((ch = getchar()) > '9' || ch < '0');
 25     a = ch - '0';
 26     while ((ch = getchar()) >= '0' && ch <= '9'){
 27         a = a * 10 + ch - '0';
 28     }
 29 }
 30 
 31 void down(int rt, int len) {
 32     if (~late[rt]) {
 33         int l = rt << 1;
 34         int r = rt << 1 | 1;
 35         int m = len >> 1;
 36 
 37         late[l] = late[r] = late[rt];
 38         seg[l] = Hotel(late[rt] * (len - m));
 39         seg[r] = Hotel(late[rt] * m);
 40         late[rt] = -1;
 41     }
 42 }
 43 
 44 Hotel up(Hotel left, Hotel right, int lLen, int rLen) {
 45     Hotel ret;
 46 
 47     ret.mx = max(left.mx, right.mx);
 48     ret.mx = max(ret.mx, left.r + right.l);
 49     ret.l = left.l;
 50     ret.r = right.r;
 51     if (left.l == lLen) ret.l += right.l;
 52     if (right.r == rLen) ret.r += left.r;
 53 
 54     return ret;
 55 }
 56 
 57 void build(int l, int r, int rt) {
 58     late[rt] = -1;
 59     if (l == r) {
 60         seg[rt] = Hotel(1);
 61 
 62         return ;
 63     }
 64     int m = (l + r) >> 1;
 65 
 66     build(lson);
 67     build(rson);
 68     seg[rt] = up(seg[rt << 1], seg[rt << 1 | 1], m + 1 - l, r - m);
 69 //    printf("@@@%d %d : %d %d %d\n", l, r, seg[rt].l, seg[rt].r, seg[rt].mx);
 70 }
 71 
 72 void update(int L, int R, int op, int l, int r, int rt) {
 73     if (L <= l && r <= R) {
 74         seg[rt] = Hotel(op * (r - l + 1));
 75         late[rt] = op;
 76 //        printf("!!!%d %d : %d %d %d\n", l, r, seg[rt].l, seg[rt].r, seg[rt].mx);
 77 
 78         return ;
 79     }
 80     int m = (l + r) >> 1;
 81 
 82     down(rt, r - l + 1);
 83     if (L <= m) update(L, R, op, lson);
 84     if (m < R) update(L, R, op, rson);
 85     seg[rt] = up(seg[rt << 1], seg[rt << 1 | 1], m + 1 - l, r - m);
 86 //    printf("!!!%d %d : %d %d %d\n", l, r, seg[rt].l, seg[rt].r, seg[rt].mx);
 87 }
 88 
 89 void deal(int len, int n) {
 90     int op, x, y;
 91 
 92     build(1, len, 1);
 93     while (n--) {
 94         scan(op);
 95         switch (op) {
 96         case 1: {
 97             //scanf("%d%d", &x, &y);
 98             scan(x);
 99             scan(y);
100             update(x, x + y - 1, 0, 1, len, 1);
101         }
102         break;
103         case 2: {
104             //scanf("%d%d", &x, &y);
105             scan(x);
106             scan(y);
107             update(x, x + y - 1, 1, 1, len, 1);
108         }
109         break;
110         case 3: {
111             printf("%d\n", seg[1].mx);
112         }
113         break;
114         default:
115             return ;
116         }
117     }
118 }
119 
120 int main() {
121     int n, p;
122 
123     while (~scanf("%d%d", &n, &p)) {
124         deal(n, p);
125     }
126 
127     return 0;
128 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/poj_1823_Lyon.html