区间问题----差分+离散化+前缀和
《二维离散化+二维前缀和+二维双指针算法+二分+以点代二维区间》


思路:
首先,利用二分,将求解问题变成判断问题,二分边长
关于在二维平面上的任意区域的数值问题可以用预处理二维前缀和解决
然后因为利用二分出来的边长,我们枚举在二维平面上的两个点,然后在通过前缀和算出这个区域上的草的数量,如果满足条件,return true;

但是如果这里不离散化是做不了的,因为按照,枚举x与y要1e8时间复杂度,
但是这里N很小,x与y最多也只会出现1000次
1000*1000=1e6复杂度可以接受
1 #include <iostream>
2 #include <cstring>
3 #include <vector>
4 #include <algorithm>
5 using namespace std;
6 typedef pair<int, int> PII;
7 const int N = 1010;
8 int c, n;
9 PII points[N];
10 vector<int> numbers;
11 int sum[N][N];
12 int get(int x)
13 {
14 int l = 1, r = numbers.size() - 1, ans = -1;
15 while (l <= r)
16 {
17 int mid = (l + r) >> 1;
18 if (numbers[mid] >= x)
19 {
20 ans = mid;
21 r = mid - 1;
22 }
23 else
24 l = mid + 1;
25 }
26 return ans;
27 }
28 bool check(int len)
29 {
//可以发现我这里双指针,我只枚举了x2,y2的值,而x1与y1我并没有枚举,而是受了x2与y2的限制而移动
30 for (int x1 = 1, x2 = 1; x2 < numbers.size(); x2++)
31 {
32 while (numbers[x2] - numbers[x1] + 1 > len)
33 x1++;
34 for (int y1 = 1, y2 = 1; y2 < numbers.size(); y2++)
35 {
36 while (numbers[y2] - numbers[y1] + 1 > len)
37 y1++;
38 if (sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1] >= c)
39 return true;
40 }
41 }
42 return false;
43 }
44 int main()
45 {
46 cin >> c >> n;
47 for (int i = 1; i <= n; i++)
48 {
49 int x, y;
50 scanf("%d%d", &x, &y);
51 points[i] = {x, y};
52 numbers.push_back(x), numbers.push_back(y);
53 }
54 numbers.push_back(0);
55 sort(numbers.begin(), numbers.end());
56 numbers.erase(unique(numbers.begin(), numbers.end()), numbers.end());
57
58 /* for (int i = 0; i < numbers.size(); i++)
59 cout << numbers[i] << " ";
60 cout << endl; */
61
62 for (int i = 1; i <= n; i++)
63 {
64 int x = get(points[i].first), y = get(points[i].second);
65 /* cout << "pos:" << x << " " << y << endl; */
66 sum[x][y]++;
67 }
68 for (int i = 1; i < numbers.size(); i++)
69 for (int j = 1; j < numbers.size(); j++)
70 sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
71 int l = 1, r = 10000, ans = -1;
72 while (l <= r)
73 {
74 int mid = (l + r) >> 1;
75 if (check(mid))
76 {
77 ans = mid;
78 r = mid - 1;
79 }
80 else
81 l = mid + 1;
82 }
83 cout << ans;
84 return 0;
85 }
《一维差分+一维以点代区间问题》

思路:这道题是明显的离散化+差分,但是这里有个坑点:一维以点代区间
像这样的要定义好点的含义,否则会影响求前缀和与差分的规则
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <vector>
5 using namespace std;
6 typedef pair<int, int> PII;
7 const int N = 2 * 1e5 + 5, INF = 1e9 + 10;
8 int pre[N], n, sum[N];
9 vector<int> dist;
10 PII arr[N];
11 int get(int x)
12 {
13 int l = 0, r = dist.size() - 1, ans;
14 while (l <= r)
15 {
16 int mid = (l + r) >> 1;
17 if (dist[mid] >= x)
18 {
19 ans = mid;
20 r = mid - 1;
21 }
22 else
23 l = mid + 1;
24 }
25 return ans;
26 }
27 int main()
28 {
29 cin >> n;
30 int pos = 0, nowpos;
31 dist.push_back(0);
32 dist.push_back(INF);
33 dist.push_back(-INF);
34 for (int i = 1; i <= n; i++)
35 {
36 int num;
37 char c[2];
38 scanf("%d", &num);
39 scanf("%s", c);
40 if (c[0] == 'R')
41 {
42
43 nowpos = pos + num;
44 arr[i] = {pos, nowpos};
45 /* cout << pos << " " << nowpos << endl; */
46 }
47 else if (c[0] == 'L')
48 {
49
50 nowpos = pos - num;
51 arr[i] = {nowpos, pos};
52 /* cout << nowpos << " " << pos << endl; */
53 }
54 pos = nowpos;
55 dist.push_back(nowpos);
56 }
57 sort(dist.begin(), dist.end());
58 dist.erase(unique(dist.begin(), dist.end()), dist.end());
59 /* for (int i = 0; i <= dist.size() - 1; i++)
60 cout << dist[i] << " ";
61 cout << endl; */
62 for (int i = 1; i <= n; i++)
63 {
64 int l = get(arr[i].first), r = get(arr[i].second);
65 /* cout << l << " " << r << endl; */
66 pre[l] += 1, pre[r] -= 1;
67 }
68 for (int i = 1; i <= dist.size() - 1; i++)
69 sum[i] = sum[i - 1] + pre[i];
70 int ans = 0;
71 for (int i = 1; i < dist.size() - 1; i++)
72 {
73 if (sum[i] >= 2)
74 ans += dist[i + 1] - dist[i];
75 }
76 cout << ans;
77 return 0;
78 }
《逆向思维的差分》


这道题要我们找出温度,但是我们不如逆向考虑一下,
对于每一头牛,给定区间[l,r];我们不如首先来一个温度轴
每一头牛,在温度[0,l-1]上产奶x,[r+1,INF]上产奶z,【l,r】上产奶y,然后可以将这些值加入到温度轴上
在全部牛枚举完后,扫一遍温度轴上的数值,然后最大值对应的温度即为答案
但是温度轴有0-1e9,但是牛有20000比较小,说明温度值出现的全部值不超过40000,用离散化
1 #include <iostream>
2 #include <cstring>
3 #include <algorithm>
4 #include <vector>
5 using namespace std;
6 const int N = 4 * 1e4 + 5;
7 int n, x, y, z;
8 vector<int> temp;
9 pair<int, int> cows[N];
10 int pre[N];
11 int get(int x)
12 {
13 int l = 0, r = temp.size() - 1, ans = -1;
14 while (l <= r)
15 {
16 int mid = (l + r) >> 1;
17 if (temp[mid] >= x)
18 {
19 ans = mid;
20 r = mid - 1;
21 }
22 else
23 l = mid + 1;
24 }
25 return ans;
26 }
27 int main()
28 {
29 cin >> n >> x >> y >> z;
30 for (int i = 1; i <= n; i++)
31 {
32 int l, r;
33 scanf("%d%d", &l, &r);
34 cows[i] = {l, r};
35 temp.push_back(l), temp.push_back(r);
36 }
37 temp.push_back(-1), temp.push_back(1e9 + 10);
38 sort(temp.begin(), temp.end());
39 temp.erase(unique(temp.begin(), temp.end()), temp.end());
40 for (int i = 1; i <= n; i++)
41 {
42 int l = get(cows[i].first), r = get(cows[i].second);
43 pre[0] += x;
44 pre[l] += y - x;
45 pre[r + 1] += z - y;
46 }
47 int ans = 0, num = 0;
48 for (int i = 0; i <= temp.size() - 1; i++)
49 {
50 num += pre[i];
51 ans = max(ans, num);
52 }
53 cout << ans;
54 return 0;
55 }

浙公网安备 33010602011771号