分治法:整体二分
整体二分主要是把所有询问放在一起二分答案,然后把操作也一起分治
当你发现多组询问可以离线的时候
当你发现询问可以二分答案而且check复杂度对于单组询问可以接受的时候
当你发现询问的操作都是一样的的时候
BZOJ3110
修改区间,查询区间第K大
1 #include "cstdio" 2 #define lowbit(x) (x & (-x)) 3 4 using namespace std; 5 6 const int Nmax = 50005; 7 8 int N, M; 9 struct Option{ 10 int sign, x, y, c; 11 }op[Nmax]; 12 13 int tot = -1, ans[Nmax]; 14 int q[Nmax], tmp[2][Nmax]; 15 16 namespace BIT{ 17 int t[Nmax][2], d[Nmax][2]; 18 19 void update(bool s, int pos, int c) 20 { 21 for (int i = pos; i <= N; i += lowbit(i)) { 22 if (t[i][s] != tot) { t[i][s] = tot; d[i][s] = 0; } 23 d[i][s] += c; 24 } 25 } 26 27 int get_sum(bool s, int pos) 28 { 29 int res = 0; 30 for (int i = pos; i; i -= lowbit(i)) { 31 if (t[i][s] != tot) { t[i][s] = tot; d[i][s] = 0; } 32 res += d[i][s]; 33 } 34 return res; 35 } 36 37 void Add(int x, int y) 38 { 39 update(0, x, 1); update(0, y + 1, -1); 40 update(1, x, x); update(1, y + 1, -(y + 1)); 41 } 42 43 int Query(int x, int y) 44 { 45 int temp = get_sum(0, y) * (y + 1) - get_sum(1, y); 46 temp -= get_sum(0, x - 1) * x - get_sum(1, x - 1); 47 return temp; 48 } 49 } 50 51 void solve(int L, int R, int l, int r) 52 { 53 if (L > R) return; 54 55 ++tot; int mid = (l + r) >> 1; 56 if (l == r) { 57 for (int i = L; i <= R; ++i) if (op[q[i]].sign == 2) ans[q[i]] = mid; 58 return; 59 } 60 61 tmp[0][0] = tmp[1][0] = 0; using namespace BIT; 62 for (int i = L; i <= R; ++i) { 63 int temp = q[i]; 64 if (op[temp].sign == 1) { 65 if (op[temp].c <= mid) tmp[0][++tmp[0][0]] = temp; 66 else { 67 tmp[1][++tmp[1][0]] = temp; 68 Add(op[temp].x, op[temp].y); 69 } 70 } else { 71 int cnt = Query(op[temp].x, op[temp].y); 72 if (cnt < op[temp].c) { 73 op[temp].c -= cnt; 74 tmp[0][++tmp[0][0]] = temp; 75 } else tmp[1][++tmp[1][0]] = temp; 76 } 77 } 78 79 int tl = L, t2 = L + tmp[0][0] - 1; 80 for (int i = 1; i <= tmp[0][0]; ++i) q[tl++] = tmp[0][i]; 81 for (int i = 1; i <= tmp[1][0]; ++i) q[tl++] = tmp[1][i]; 82 solve(L, t2, l, mid); solve(t2 + 1, R, mid + 1, r); 83 } 84 85 int main() 86 { 87 scanf("%d%d", &N, &M); 88 for (int i = 1; i <= M; ++i) { 89 scanf("%d%d%d%d", &op[i].sign, &op[i].x, &op[i].y, &op[i].c); 90 q[i] = i; 91 } 92 solve(1, M, 1, N); 93 for (int i = 1; i <= M; ++i) { 94 if (op[i].sign == 2) printf("%d\n", ans[i]); 95 } 96 97 return 0; 98 }