操作:
1,从数列结尾插入一个数。
2,查询区间第k小。
3,查询一个数在当前序列是第几小。
4,查询当前序列第k小。
1,离线。因为结尾插入一个数并不会对当前查询的区间造成影响。
2和4,划分树。
3,其实就是划分树的逆过程。
划分树就是二分一个区间,把小于等于区间中心的数放到左边,否则放到右边。
同时还需要记录一个位置,在它位置之前(包括它的位置),有多少个被放到了左区间。
当完全递归到区间长度是1时,就把一个数列排好序了。
1 #include<cstdio> 2 #include<algorithm> 3 #define MAXM 20 4 #define MAXN 300010 5 typedef long long LL; 6 using namespace std; 7 struct node { 8 int kind; 9 int x, st, nd; 10 }; 11 node p[MAXN]; 12 int tree[MAXM][MAXN], num[MAXM][MAXN], sorted[MAXN]; 13 void Build(int depth, int L, int R) { 14 if (L == R) 15 return; 16 int same, mid, i, left, right; 17 mid = (L + R) >> 1; 18 same = mid - L + 1; 19 left = L; 20 right = mid + 1; 21 for (i = L; i <= R; i++) { 22 if (tree[depth][i] < sorted[mid]) 23 same--; 24 } 25 for (i = L; i <= R; i++) { 26 if (tree[depth][i] < sorted[mid]) 27 tree[depth + 1][left++] = tree[depth][i]; 28 else if (tree[depth][i] == sorted[mid] && same) { 29 tree[depth + 1][left++] = tree[depth][i]; 30 same--; 31 } else 32 tree[depth + 1][right++] = tree[depth][i]; 33 num[depth][i] = num[depth][L - 1] + left - L; 34 } 35 Build(depth + 1, L, mid); 36 Build(depth + 1, mid + 1, R); 37 } 38 int Kth(int depth, int L, int R, int x, int y, int k) { 39 if (L == R) 40 return tree[depth][L]; 41 int mid, left, pre; 42 mid = (L + R) >> 1; 43 left = num[depth][y] - num[depth][x - 1]; 44 pre = num[depth][x - 1] - num[depth][L - 1]; 45 if (left >= k) 46 return Kth(depth + 1, L, mid, L + pre, L + pre + left - 1, k); 47 else { 48 k -= left; 49 pre = x - L - pre; 50 left = y - x + 1 - left; 51 return Kth(depth + 1, mid + 1, R, mid + pre + 1, mid + pre + left, k); 52 } 53 } 54 int Value(int depth, int L, int R, int x, int y, int val) { 55 if (L == R) 56 return 1; 57 int mid, pre, left; 58 mid = (L + R) >> 1; 59 left = num[depth][y] - num[depth][x - 1]; 60 pre = num[depth][x - 1] - num[depth][L - 1]; 61 if (val <= sorted[mid]) 62 return Value(depth + 1, L, mid, L + pre, L + pre + left - 1, val); 63 else { 64 pre = x - L - pre; 65 return left 66 + Value(depth + 1, mid + 1, R, mid + 1 + pre, 67 mid + pre + y - x + 1 - left, val); 68 } 69 } 70 int main() { 71 char cmd[10]; 72 int ca = 1; 73 int n, cnt, q, i; 74 LL ans1, ans2, ans3; 75 while (~scanf("%d", &q)) { 76 ans1 = ans2 = ans3 = 0; 77 for (i = n = 0; i < q; i++) { 78 scanf(" %s", cmd); 79 if (cmd[0] == 'I') { 80 p[i].kind = 0; 81 scanf("%d", &p[i].x); 82 n++; 83 sorted[n] = tree[0][n] = p[i].x; 84 } else { 85 p[i].kind = cmd[6] - '0'; 86 if (p[i].kind == 1) 87 scanf("%d%d%d", &p[i].st, &p[i].nd, &p[i].x); 88 else 89 scanf("%d", &p[i].x); 90 } 91 } 92 sort(sorted + 1, sorted + n + 1); 93 Build(0, 1, n); 94 for (i = cnt = 0; i < q; i++) { 95 if (p[i].kind == 0) 96 cnt++; 97 else if (p[i].kind == 1) 98 ans1 += Kth(0, 1, n, p[i].st, p[i].nd, p[i].x); 99 else if (p[i].kind == 2) 100 ans2 += Value(0, 1, n, 1, cnt, p[i].x); 101 else 102 ans3 += Kth(0, 1, n, 1, cnt, p[i].x); 103 } 104 printf("Case %d:\n", ca++); 105 printf("%I64d\n%I64d\n%I64d\n", ans1, ans2, ans3); 106 } 107 return 0; 108 }