cychester

Luogu2161 [SHOI2009]会场预约-线段树

Solution

线段树维护 sum 表示区间内预约个数, L 表示区间最左边的预约, R 表示区间最右边的预约。

$pushup$ 就是这样 : 

1 void up(int nd) {
2         sum[nd] = sum[lson] + sum[rson] - (R[lson] == L[rson] && R[lson]);
3         L[nd] = L[lson]; R[nd] = R[rson];
4 }

 

每次查询答案类似于$pushup$。 

考虑把旧预约删去 :

若该次新预约 开始时间为$l$, 结束时间为$r$,是第$i$ 个预约, 则将 与该区间在右边 和 在左边相交的 旧预约的区间都用0覆盖。

然后再把新预约的区间都用 $i$覆盖。

$pushdown$ 和 $laz$ 数组也有些细节

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define rd read()
  5 using namespace std;
  6 
  7 const int N = 2e5 + 5;
  8 const int end = 1e5;
  9 
 10 struct met {
 11     int L, R;
 12 }in[N];
 13 
 14 int read() {
 15     int X = 0, p = 1; char c = getchar();
 16     for (; c > '9' || c < '0'; c = getchar())
 17         if (c == '-') p = -1;
 18     for (; c >= '0' && c <= '9'; c = getchar())
 19         X = X * 10 + c - '0';
 20     return X * p;
 21 }
 22 
 23 namespace SegT {
 24     int sum[N << 2], L[N << 2], R[N << 2], laz[N << 2];
 25     struct node {
 26         int sum, L, R;
 27     };
 28 #define lson nd << 1
 29 #define rson nd << 1 | 1
 30 #define mid ((l + r) >> 1)
 31     void up(int nd) {
 32         sum[nd] = sum[lson] + sum[rson] - (R[lson] == L[rson] && R[lson]);
 33         L[nd] = L[lson]; R[nd] = R[rson];
 34     }
 35 
 36     void make(int nd, int x) {
 37         sum[nd] = x ? 1 : 0; L[nd] = R[nd] = laz[nd] = x;
 38     }
 39 
 40     void down(int nd) {
 41         if (~laz[nd]) {
 42             make(lson, laz[nd]); make(rson, laz[nd]);
 43             laz[nd] = -1;
 44         }
 45     }
 46 
 47     void modify(int cl, int cr, int c, int l, int r, int nd) {
 48         if (cl <= l && r <= cr) {
 49             make(nd, c); return;
 50         }
 51         down(nd);
 52         if (mid >= cl)
 53             modify(cl, cr, c, l, mid, lson);
 54         if (mid < cr)
 55             modify(cl, cr, c, mid + 1, r, rson);
 56         up(nd);
 57     }
 58 
 59     node query(int cl, int cr ,int l, int r, int nd) {
 60         if (cl <= l && r <= cr) {
 61             node tmp;
 62             tmp.sum = sum[nd]; tmp.L = L[nd]; tmp.R = R[nd];
 63             return tmp;
 64         }
 65         node tmp, ls, rs;
 66         down(nd);
 67         if (mid >= cl && !(mid < cr))
 68             return query(cl, cr, l, mid, lson);
 69         else if (!(mid >= cl) && mid < cr)
 70             return query(cl, cr, mid + 1, r, rson);
 71         ls = query(cl, cr, l, mid, lson);
 72         rs = query(cl, cr, mid + 1, r, rson);
 73         tmp.sum = ls.sum + rs.sum - (ls.R == rs.L && ls.R);
 74         tmp.L = ls.L; tmp.R = rs.R;
 75         return tmp;
 76     }
 77 }using namespace SegT;
 78 
 79 int main()
 80 {
 81     int n = rd;
 82     memset(laz, -1, sizeof(laz));
 83     for (int i = 1; i <= n; ++i) {
 84         char ch = getchar();
 85         while (ch > 'Z' || ch < 'A') ch = getchar();
 86         if (ch == 'A') {
 87             int l = rd, r = rd;
 88             in[i].L = l; in[i].R = r;
 89             node ans = query(l, r, 1, end, 1);
 90             printf("%d\n", ans.sum);
 91             if (ans.L) modify(in[ans.L].L, in[ans.L].R, 0, 1, end, 1);
 92             if (ans.R) modify(in[ans.R].L, in[ans.R].R, 0, 1, end, 1);
 93             modify(l, r, i, 1, end, 1);
 94         }
 95         else {
 96             node ans = query(1, end, 1, end, 1);
 97             printf("%d\n", ans.sum);
 98         }
 99     }
100 }
View Code

 

posted on 2018-10-17 14:27  cychester  阅读(204)  评论(0编辑  收藏  举报

导航