可以利用线段树,st表
模板+模拟
思路:
1.利用st表,先算出每个区间内的最大值
2.模拟:
2.1因为true要求的条件更加苛刻,所以先对true分析:
1.两端年份存在 2.年份连续 3.俩年份内的最大值小于右端 4.左端降雨量小于等于右端
2.2 对false分析:
1.特判:如果左端不存在需要左移,因为这个点在计算的范围内(如果你不用lower_bound当我没说)
2.如果左端存在,则:中间的值要大于等于左端,这样右端只可能大于左端false,如果小于还是false
3.如果右端存在,则:中间的值要大于等于右端
4.如果两端都存在,则:右端>左端
2.3 如果都不满足,则maybe
还要注意些条件,都在代码里
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long//开LL,不然运行错误
const int N = 1e5 + 10;
int f[N][22];
int y[N], w[N];
void st(int n) {
for (int i = 1; i <= n; i++) f[i][0] = w[i];
for (int j = 1; j <= 20; j++) {
for (int i = 1; i+(1LL<<j)-1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1LL << (j-1))][j - 1]);//记住里面的顺序(1<<(j-1)),经常出错
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> y[i] >> w[i];
}
st(n);
cin >> m;
while (m--) {
int xx, yy;
cin >> yy >> xx;
int dr = lower_bound(y + 1, y + 1 + n, xx)-y;//X右边端点
int dl = lower_bound(y + 1, y + 1 + n, yy) - y;//Y左边端点
//int lx = (dr - dl) == xx - yy;//是否连续
//判断两年份是否存在,否则会出现假连续的情况:如两年份都不存在
int bl = yy == y[dl];
int br = xx == y[dr];
//特判
if (!bl) dl--;//防止这个数没有算
//st表
int k = log2(dr - dl-1);
int v = 0;//求区间内的最大降雨量
if(dl+1<=dr-1) v= max(f[dl + 1][k], f[dr - (1LL << k)][k]);//一定要有这个条件特判,不然只能对一半。中间值存在
//输出
if (bl && br && (dr - dl) == xx - yy && v < w[dr] && w[dr] <= w[dl]) cout << "true\n";
else if ((bl&& v >= w[dl]) || (br && v >= w[dr]) || (bl && br && w[dl] < w[dr])) cout << "false\n";
else cout << "maybe\n";
}
return 0;
}