【题解】洛谷 P2471 [SCOI2007] 降雨量 [线段树 + 逻辑]
P2471 [SCOI2007] 降雨量 - 洛谷 (luogu.com.cn)(下位蓝,甚至感觉上位绿)
虽然 st 表更好打,但是好久没练线段树了。
离散化区间 RMQ,可以用区间 线段树 or st 表 求最大值。
难在分讨:
(1)问的 y 和 x 都是未知年份(不知道降雨量)
此时输出 “maybe”。
(2)问的 y 是未知年份,x 已知
(可以假设 y 大于等于 x)
如果 y + 1 到 x - 1 这段已知年份的最大值小于 x 的降雨量,输出 “maybe”。
否则输出 “false”。
(3)问的 y 已知,x 是未知年份
(可以假设 x 和 y 相等,然后如(2))
如果 y + 1 到 x - 1 这段已知年份的最大值小于 y 的降雨量,输出 “maybe”。
否则输出 “false”。
(4)问的 x 和 y 都已知
如果 x 的降雨量大于 y 的降雨量,输出 “false”。(不符合题意)
如果 y + 1 到 x - 1 这段已知年份的最大值小于 x 的降雨量:
如果这段没有未知年份,输出 “true”。
(设 = x 在整个年份数组的离散值 - y 在整个年份数组的离散值 + 1 代表着 y 到 x 这
一段已知年份的的数量, = x - y + 1代表着 y 到 x 这一段年份数量,如果两者相
等,就代表着这段没有未知年份)
否则输出 “maybe”
否则输出 “false”。
注意边界。
代码:
#include<bits/stdc++.h>
using namespace std;const int N = 5e4 + 10;
#define lc(p) p << 1
#define rc(p) ((p << 1) | 1)int n, a[N], c[N];
map<int, int> mp_a;struct node {int l, r;int mx;
} tr[N * 4];void pushup(int p) {tr[p].mx = max(tr[lc(p)].mx, tr[rc(p)].mx);
}void build(int p, int l, int r) {tr[p] = {l, r, 0};if (l == r) {tr[p].mx = c[l];return ;}int mid = (l + r) >> 1;build(lc(p), l, mid);build(rc(p), mid + 1, r);pushup(p);
}int query(int p, int l, int r) {if (l > r) {return 0;}if (r < tr[p].l || tr[p].r < l) {return 0;}if (l <= tr[p].l && tr[p].r <= r) {return tr[p].mx;}return max(query(lc(p), l, r), query(rc(p), l, r));
}int main () {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; i ++) {cin >> a[i] >> c[i];mp_a[a[i]] = i;}int m;cin >> m;build(1, 1, n);for (int i = 1; i <= m; i ++) {int y, x;cin >> y >> x; if ((!mp_a[y]) && (!mp_a[x])) { // x 和 y 都是未知年份 cout << "maybe\n";continue;} if (y + 1 > a[n] || x - 1 < a[1]) { // 防止越界 cout << "maybe\n";continue;}auto l = lower_bound(a + 1, a + n + 1, y + 1);auto r = lower_bound(a + 1, a + n + 1, x);r --;int st = mp_a[*l], ed = mp_a[*r]; // y + 1 到 x - 1 这段已知年份的已知开头和结尾的离散值 int mx = query(1, st, ed); // y + 1 到 x - 1 这段已知年份的最大值if ((!mp_a[y]) && (mp_a[x])) { // y 是未知年份,x 已知int t = mp_a[x];if (mx < c[t]) {cout << "maybe\n";}else {cout << "false\n";}}else if ((mp_a[y]) && (!mp_a[x])) { // y 已知,x 是未知年份int t = mp_a[y];if (mx < c[t]) {cout << "maybe\n";}else {cout << "false\n";}}else {int tx = mp_a[x], ty = mp_a[y];if (c[tx] > c[ty]) { // x 的降雨量大于 y 的降雨量cout << "false\n";continue;}if (mx < c[tx]) { // y + 1 到 x - 1 这段已知年份的最大值小于 xif (tx - ty + 1 == x - y + 1) { // 没有未知年份cout << "true\n";}else {cout << "maybe\n";}}else {cout << "false\n";}}}return 0;
}
