P2471 [SCOI2007] 降雨量 題解

FRZ_29發表於2024-09-09

題目傳送門

分析

分討題。

首先發現是 RMQ 問題(區間最值),可以用線段樹或 ST 表來維護(程式碼為線段樹 ,因為我忘記 ST 表怎麼寫了)。

然後發現有些年份不明確導致區間判斷似乎不好搞。

但事實上只要判斷下標差是否等於年份差即可得出該區間有無不明確年份。

其次考慮“必真”,“必假”,“有可能”三種結果的優先順序。

稍微想想就會發現 \(\text{False} \gt \text{Maybe} \gt \text{True}\)

於是先考慮 \(\text{False}\)

  1. 如果 \(X\) 明確,且 \(Y + 1 \sim X - 1\) 區間記憶體在 \(Z, r_Z \ge r_X\)
  2. 如果 \(Y\) 明確,且 \(Y + 1 \sim X - 1\) 區間記憶體在 \(Z, r_Z \ge r_Y\)
  3. 如果 \(X, Y\) 明確,且 \(r_X \gt r_Y\)

然後考慮 \(\text{Maybe}\)(此時必然不滿足上述條件)。

  1. 如果 \(X, Y\) 明確,且 \(Y + 1 \sim X - 1\) 區間記憶體在 \(Z\) 不明確。

  2. 如果 \(X\) 不明確。

  3. 如果 \(Y\) 不明確。

以上條件不滿足的自然是 \(\text{True}\) 了。

點選檢視程式碼
/*
--------------------------------
|        code by FRZ_29        |
|          code  time          |
|          2024/09/09          |
|           12:15:58           |
|            星期一             |
--------------------------------
                                */

#include <iostream>
#include <climits>
#include <cstdio>
#include <ctime>

using namespace std;

void RD() {}
template<typename T, typename... U> void RD(T &x, U&... arg) {
    x = 0; int f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    x *= f; RD(arg...);
}

const int N = 5e4 + 5;

#define LS (rt << 1)
#define RS (rt << 1 | 1)
#define MID (l + r >> 1)
#define PRINT(x) cout << #x << " = " << x << "\n"
#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)

int n, y[N], _r[N], Max[N << 2], m;

void up(int rt) {
    Max[rt] = max(Max[LS], Max[RS]);
}

void build(int rt, int l, int r) {
    if (l == r) {
        Max[rt] = _r[l];
        return;
    }

    build(LS, l, MID), build(RS, MID + 1, r);
    up(rt);
}

int query(int rt, int l, int r, int L, int R) {
    if (L <= l && r <= R) return Max[rt];
    int ans = 0;
    if (MID >= L) ans = max(ans, query(LS, l, MID, L, R));
    if (MID < R) ans = max(ans, query(RS, MID + 1, r, L, R));
    return ans;
}

int main() {
   freopen("read.in", "r", stdin);
   freopen("out.out", "w", stdout);
//    time_t st = clock();
    RD(n);
    LF(i, 1, n) RD(y[i], _r[i]);
    build(1, 1, n);
    RD(m);
    while (m--) {
        int X, Y, ans = 0; RD(X, Y);
        int st = lower_bound(y + 1, y + n + 1, X) - y,
            ed = lower_bound(y + 1, y + n + 1, Y) - y;
        bool is_st = y[st] == X, is_ed = y[ed] == Y;
        if (!is_st) st--;
        if (st + 1 <= ed - 1) ans = query(1, 1, n, st + 1, ed - 1);
        if ((ans >= _r[ed] && is_ed) || (ans >= _r[st] && is_st) || (_r[st] < _r[ed] && is_st && is_ed)) puts("false");
        else if ((ed - st != y[ed] - y[st] && is_ed && is_st) || !is_st || !is_ed) puts("maybe");
        else puts("true");
    }
//    printf("\n%dms", clock() - st)
    return 0;
}

/* ps:FRZ弱爆了 */