思路1:
平方分割。
实现:
1 #include <cstdio> 2 #include <algorithm> 3 #include <vector> 4 #include <cmath> 5 using namespace std; 6 const int MAXN = 100005; 7 const int B = 1000; 8 int n, m, a[MAXN], nums[MAXN]; 9 vector<int> v[MAXN / B]; 10 bool check(int x, int l, int r, int k) 11 { 12 int ans = 0; 13 while (l < r && l % B) if (a[l++] <= nums[x]) ans++; 14 while (r > l && r % B) if (a[--r] <= nums[x]) ans++; 15 for (int i = l / B; i < r / B; i++) 16 { 17 ans += upper_bound(v[i].begin(), v[i].end(), nums[x]) - v[i].begin(); 18 } 19 return ans >= k; 20 } 21 int main() 22 { 23 scanf("%d %d", &n, &m); 24 for (int i = 0; i < n; i++) 25 { 26 scanf("%d", &a[i]); 27 nums[i] = a[i]; 28 v[i / B].push_back(a[i]); 29 } 30 for (int i = 0; i <= n / B; i++) sort(v[i].begin(), v[i].end()); 31 sort(nums, nums + n); 32 int x, y, k; 33 for (int i = 0; i < m; i++) 34 { 35 scanf("%d %d %d", &x, &y, &k); 36 x--; 37 int l = 0, r = n - 1, ans = -1; 38 while (l <= r) 39 { 40 int m = l + r >> 1; 41 if (check(m, x, y, k)) { r = m - 1; ans = m; } 42 else l = m + 1; 43 } 44 printf("%d ", nums[ans]); 45 } 46 return 0; 47 }
思路2:
归并树。
实现:
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 const int MAXN = 100005; 6 vector<int> tree[MAXN * 4], nums; 7 int n, m, a[MAXN]; 8 9 void build(int num, int l, int r) 10 { 11 if (l == r) { tree[num].push_back(a[l]); return; } 12 int m = l + r >> 1, lc = num * 2, rc = num * 2 + 1; 13 build(lc, l, m); 14 build(rc, m + 1, r); 15 tree[num].resize(r - l + 1); 16 merge(tree[lc].begin(), tree[lc].end(), tree[rc].begin(), tree[rc].end(), tree[num].begin()); 17 } 18 19 int query(int x, int y, int d, int num, int l, int r) 20 { 21 if (y < l || x > r) return 0; 22 if (x <= l && y >= r) return upper_bound(tree[num].begin(), tree[num].end(), d) - tree[num].begin(); 23 int m = l + r >> 1, ans = 0; 24 if (x <= m) ans += query(x, y, d, num * 2, l, m); 25 if (y >= m + 1) ans += query(x, y, d, num * 2 + 1, m + 1, r); 26 return ans; 27 } 28 29 bool check(int x, int y, int d, int k) 30 { 31 int ans = query(x, y, nums[d], 1, 1, n); 32 return ans >= k; 33 } 34 35 int main() 36 { 37 scanf("%d %d", &n, &m); 38 nums.push_back(0); 39 for (int i = 1; i <= n; i++) 40 { 41 scanf("%d", &a[i]); 42 nums.push_back(a[i]); 43 } 44 sort(nums.begin() + 1, nums.end()); 45 build(1, 1, n); 46 int x, y, k, ans = -1; 47 for (int i = 0; i < m; i++) 48 { 49 scanf("%d %d %d", &x, &y, &k); 50 int l = 1, r = n; 51 while (l <= r) 52 { 53 int m = l + r >> 1; 54 if (check(x, y, m, k)) r = m - 1, ans = m; 55 else l = m + 1; 56 } 57 printf("%d ", nums[ans]); 58 } 59 return 0; 60 }