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 }