NC20259 [SCOI2007]降雨量

题目链接

题目

题目描述

我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意 Y<Z<X,Z年的降雨量严格小于X年。

例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890, 则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。

输入描述

输入仅一行包含一个正整数n,为已知的数据。
以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小 到大排列,即yi<yi+1。
下一行包含一个正整数m,为询问的次数。
以下m行每行包含两个数Y和X,即询问“X年是自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。

输出描述

对于每一个询问,输出true,false或者maybe。

示例1

输入

6
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008

输出

false
true
false
maybe
false

备注

100%的数据满足:1n50000,1m10000,109yi109,1ri109

题解

知识点:线段树,离散化。

数据范围显然需要离散化,然后就是普通的区间最大值查询,但是分类讨论年份左右端点会很麻烦:

  1. 左右是完全相等的,直接 true
  2. 左右都不存在,直接 maybe
  3. 左存在右不存在,如果已知的区间长度为 1 或除去右端点的区间最大值小于右端点值,则 maybe ;否则 false
  4. 左不存在右存在,如果已知的区间长度为 1 或除去左端点的区间最大值小于左端点值,则 maybe ;否则 false
  5. 左右都存在,若左端点值大于等于右端点值,且区间长度为1或2或除去左右端点的区间最大值小于右端点值,则继续判断;否则 false 。若满足条件,则若已知的区间长度等于实际年份跨度,则 true ;否则 maybe

时间复杂度 O((n+m)logn)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct T {
int mx;
static T e() { return { (int)-2e9 }; }
friend T operator+(const T &a, const T &b) { return { max(a.mx,b.mx) }; }
};
template<class T>
class SegmentTree {
int n;
vector<T> node;
T query(int rt, int l, int r, int x, int y) {
if (r < x || y < l) return T::e();
if (x <= l && r <= y) return node[rt];
int mid = l + r >> 1;
return query(rt << 1, l, mid, x, y) + query(rt << 1 | 1, mid + 1, r, x, y);
}
public:
SegmentTree() {}
SegmentTree(const vector<T> &src) { init(src); }
void init(const vector<T> &src) {
assert(src.size());
n = src.size() - 1;
node.assign(n << 2, T::e());
function<void(int, int, int)> build = [&](int rt, int l, int r) {
if (l == r) return node[rt] = src[l], void();
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
node[rt] = node[rt << 1] + node[rt << 1 | 1];
};
build(1, 1, n);
}
T query(int x, int y) { return query(1, 1, n, x, y); }
};
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<T> a(n + 1);
vector<int> y_src(n + 1);
for (int i = 1;i <= n;i++) {
int y, r;
cin >> y >> r;
a[i] = { r };
y_src[i] = y;
}
auto get = [&](int x)->int { return lower_bound(y_src.begin() + 1, y_src.end(), x) - y_src.begin(); };
SegmentTree<T> sgt(a);
int m;
cin >> m;
while (m--) {
int l, r;
cin >> l >> r;
if (l > r) {
cout << "false" << '\n';
continue;
}//* 题意不明
if (l == r) {
cout << "true" << '\n';
continue;
}
int rkl = get(l), rkr = get(r);
if (y_src[rkl] != l && y_src[rkr] != r) cout << "maybe" << '\n';
else if (y_src[rkl] != l) {
if (rkl == rkr || sgt.query(rkl, rkr - 1).mx < a[rkr].mx) cout << "maybe" << '\n';
else cout << "false" << '\n';
}
else if (y_src[rkr] != r) {
if (rkl + 1 == rkr || sgt.query(rkl + 1, rkr - 1).mx < a[rkl].mx) cout << "maybe" << '\n';
else cout << "false" << '\n';
}
else if (a[rkl].mx >= a[rkr].mx && (rkl == rkr || rkl + 1 == rkr || sgt.query(rkl + 1, rkr - 1).mx < a[rkr].mx)) {
if (r - l > rkr - rkl) cout << "maybe" << '\n';
else cout << "true" << '\n';
}
else cout << "false" << '\n';
}
return 0;
}
posted @   空白菌  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示