P2471 [SCOI2007]降雨量
题目描述
我们常常会说这样的话:“X 年是自 Y 年以来降雨量最多的”。它的含义是 X 年的降雨量不超过 Y 年,且对于任意 Y<Z<X,Z 年的降雨量严格小于 X 年。例如 2002,2003,2004 和 2005 年的降雨量分别为 4920,5901,2832 和 3890,则可以说“2005 年是自 2003 年以来最多的”,但不能说“2005 年是自 2002 年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。题目link
思路
先判false:
1、当右端点年份确定,且中间年份最大降雨量大于等于右端点降雨量
2、当左端点年份确定,且中间年份最大降雨量大于等于左端点降雨量
3、当左右端点年份都确定,且左端点降雨量小于等于右端点降雨量
再判maybe:
1、当左右端点之差不等于左右端点年份之差(等价于年份不连续,也就是我前面所说的更好的判断区间连续的方法)
2、左端点年份不确定
3、右端点年份不确定
(因为已经切掉false的情况了,那么剩下的情况中可以直接照上面的判断!)
最后判断true
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 50010;
int y[N], rr[N];
int n, m;
const int M = 17;
int f[N][M];//表示i开始,长度为2^j的最大值
void init() {
for(int j=0; j<M; ++j)//长度从2^0到2^M枚举
for(int i=1; i+(1<<j)-1<=n; ++i) {//位置从1到1+len-1<=n
if(!j) f[i][j] = rr[i];
else f[i][j] = max(f[i][j-1], f[i+(1<<j-1)][j-1]);//从i+2^(j-1)
}
}
int query(int l, int r) {//下表为l~r中返回最大的数
int len = r - l + 1;
int k = log2(len);
return max(f[l][k], f[r-(1<<k)+1][k]);//f[l,k], f[r-2^k,k]
}
signed main()
{
cin>>n;
for(int i=1; i<=n; ++i) {
scanf("%lld%lld", &y[i], &rr[i]);
}
init();
cin>>m;
while(m--) {
int y1, y2;
scanf("%lld%lld", &y1, &y2);
if(y1>=y2){printf("false\n");continue;}
int st=lower_bound(y+1,y+n+1,y1)-y,ed=lower_bound(y+1,y+n+1,y2)-y;
bool fl,fr;int op=0;
fl=y[st]==y1,fr=y[ed]==y2;
if(!fl)st--;
if(st+1<=ed-1)op=query(st+1,ed-1);
if((op>=rr[ed]&&fr)||(rr[st]<rr[ed]&&fl&&fr)||(op>=rr[st]&&fl))printf("false\n");
else if(ed-st!=y[ed]-y[st]||!fr||!fl)printf("maybe\n");
else printf("true\n");
}
return 0;
}