http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2610
1 13 5 6 9 5 2 3 6 8 7 3 2 5 1 4 1 13 1 10 1 13 3 6 3 6 3 6 2 8 2 8 1 9 1 9
Case #1: 13 7 3 6 9
分析:
题意是说给你一串数字,求在动态区间[L , R]内的在[A , B]范围内的数的个数。
数据很大,一般的方法会超。
官方标程:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 #define lson l, m, rt->left 9 #define rson m + 1, r, rt->right 10 11 const int maxn = 55555; 12 13 struct Node { 14 int sum; 15 Node *left, *right; 16 }*root[maxn], tree[2000000], *idx; 17 18 int num[maxn], p[maxn], mp[maxn]; 19 int n, m; 20 int tol; 21 22 23 inline Node* nextNode() { 24 idx->sum = 0; 25 idx->left = idx->right = NULL; 26 return idx++; 27 } 28 29 inline Node* copyNode(Node* temp) { 30 idx->sum = temp->sum; 31 idx->left = temp->left; 32 idx->right = temp->right; 33 return idx++; 34 } 35 36 inline bool cmp(int a, int b) { 37 return num[a] < num[b]; 38 } 39 40 void input() { 41 scanf("%d%d", &n, &m); 42 for(int i = 1; i <= n; i++) { 43 scanf("%d", &num[i]); 44 p[i] = i; 45 } 46 sort(p + 1, p + n + 1, cmp); 47 int pre = -0x7f7f7f7f; 48 tol = 0; 49 for(int i = 1; i <= n; i++) { 50 if(num[ p[i] ] == pre) { 51 num[ p[i] ] = tol; 52 } 53 else { 54 pre = num[ p[i] ]; 55 mp[ ++tol ] = num[ p[i] ]; 56 num[ p[i] ] = tol; 57 } 58 } 59 } 60 61 void build(int l, int r, Node* rt) { 62 if(l == r) return; 63 int m = (l + r) >> 1; 64 rt->left = nextNode(); 65 rt->right = nextNode(); 66 build(lson); 67 build(rson); 68 } 69 70 int query(int ll, int rr, int l, int r, Node* rtl, Node* rtr) { 71 if(ll <= l && r <= rr) { 72 return rtr->sum - rtl->sum; 73 } 74 int m = (l + r) >> 1; 75 int ret = 0; 76 if(ll <= m) ret += query(ll, rr, l, m, rtl->left, rtr->left); 77 if(rr > m) ret += query(ll, rr, m + 1, r, rtl->right, rtr->right); 78 return ret; 79 } 80 81 Node* add(int x, int l, int r, Node* rt) { 82 Node* temp = copyNode(rt); 83 if(l == r) { 84 temp->sum++; 85 return temp; 86 } 87 int m = (l + r) >> 1; 88 if(x <= m) temp->left = add(x, lson); 89 else temp->right = add(x, rson); 90 temp->sum = temp->left->sum + temp->right->sum; 91 return temp; 92 } 93 94 void build() { 95 idx = tree; 96 root[0] = nextNode(); 97 build(1, tol, root[0]); 98 for(int i = 1; i <= n; i++) { 99 root[i] = add(num[i], 1, tol, root[i - 1]); 100 } 101 } 102 103 inline int bin1(int x) { //find the left-most number that is >= x 104 int left = 1, right = tol; 105 int ans = -1; 106 while(left <= right) { 107 int mid = (left + right) >> 1; 108 if(mp[mid] >= x) { 109 ans = mid; 110 right = mid - 1; 111 } 112 else left = mid + 1; 113 } 114 return ans; 115 } 116 117 inline int bin2(int x) { // find the right-most number that is <= x 118 int left = 1, right = tol; 119 int ans = -1; 120 while(left <= right) { 121 int mid = (left + right) >> 1; 122 if(mp[mid] <= x) { 123 ans = mid; 124 left = mid + 1; 125 } 126 else right = mid - 1; 127 } 128 return ans; 129 } 130 131 void solve() { 132 static int cas = 1; 133 printf("Case #%d:\n", cas++); 134 while(m--) { 135 int l, r, a, b; 136 scanf("%d%d%d%d", &l, &r, &a, &b); 137 a = bin1(a); 138 b = bin2(b); 139 if(a == -1 || b == -1) { 140 puts("0"); 141 continue; 142 } 143 printf("%d\n", query(a, b, 1, tol, root[l - 1], root[r])); 144 } 145 } 146 147 int main() { 148 //freopen("input.in", "r", stdin); 149 //freopen("output.out", "w", stdout); 150 151 int __t; 152 scanf("%d", &__t); 153 while(__t--) { 154 input(); 155 build(); 156 solve(); 157 } 158 return 0; 159 }