poj2104 K-th Number

思路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 }
原文地址:https://www.cnblogs.com/wangyiming/p/8453190.html