1. 程式人生 > >Luogu2161 [SHOI2009]會場預約-線段樹

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