1067: [SCOI2007]降雨量
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4026 Solved: 1067
[Submit][Status][Discuss]
Description
我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意
Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,
则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未
知,有的说法是可能正确也可以不正确的。
Input
输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小
到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是
自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。
Output
对于每一个询问,输出true,false或者maybe。
Sample Input
6
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008
Sample Output
false
true
false
maybe
false
HINT
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9
这道题真的好坑好坑,而且这道题要看清题意,这里就算是语文题吧,做了好久才做出来。
具体做法有线段树维护区间最大值,或者RMQ-ST预处理,然后分类讨论
这里分好多种情况:
我们这里定 从X年到Y年:
1. X>Y的情况应该可以排除不用考虑
2. X为最大的一年
3. Y为最小的一年,2,3这两点也可以不判断,不过判断了没事
4. 接下来就是重点了:
5. true的情况有:
6. X,Y都已知,且X-1到Y-1年的降雨量要小于Y,且Y年的降雨量不超过X年,并且X年到Y年都要连续的.
7. maybe的情况有:
8. X,Y都未知
9. X,Y这两年中其中有一年未知,X未知,X到Y-1年中任何一年的降雨量都小于Y年。Y未知,X+1到Y年中的任何一年的降雨量都小于X年。
10. X,Y都已知,且X-1到Y-1年的降雨量要小于Y,Y年的降雨量不超过X年,且X+1到Y-1年中至少有一年是未知的。
11. 其他情况就是false了。
RMQ-ST做法:
/**************************************************************
Problem: 1067
User: _ostreamBaba
Language: C++
Result: Accepted
Time:172 ms
Memory:5012 kb
****************************************************************/
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)
#define MOD 1000000007
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 60;
using namespace std;
//#define TIME
inline int read(){
int x(0),f(1);
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int dpmax[17][50010];
int year[50010];
int rain[50010];
int N, M;
void rmq(int limits){ //预处理
for(int i = 1; i < limits; ++i){
for(int j = 1; j <= N; ++j){
if(j+(1<<i)-1 <= N){
dpmax[i][j] = max(dpmax[i-1][j], dpmax[i-1][j+(1<<i>>1)]);
}
}
}
}
inline int query(int l, int r){//区间求最值
if(l > r){ //这种情况是x,y年都已知,且x+1==y
return -INF;
}
else{
int k = floor(log2(r-l+1));
return max(dpmax[k][l], dpmax[k][r-(1<<k)+1]);
}
}
inline int getpos(int p)//获得位置
{
int pos = lower_bound(year+1, year+N+1, p)-year;
return pos;
}
int main()
{
// fin;
// fout;
N = read();
mes(dpmax, 0);
for(int i = 1; i <= N; ++i){
year[i] = read();
rain[i] = read();
dpmax[0][i] = rain[i];
}
rmq(log2(N)+1);
M = read();
while(M--){
int x, y, l, r, max_rain;
x = read();
y = read();
l = getpos(x);
r = getpos(y);
// cout << query(l, r) << endl;
bool _l = (l<=N&&year[l]==x); // find or no_find
bool _r = (r<=N&&year[r]==y); // find or no_find
if(_r == false){ //找不到的话会越界,控制在N内
--r;
}
if(_r && r == 1){
printf("maybe\n");
continue;
}
else if(_l && l == N){
printf("maybe\n");
continue;
}
if(!_l && !_r){
printf("maybe\n");
}
else if(!_l && _r){
max_rain = query(l, r-1);
if(max_rain < rain[r]){
printf("maybe\n");
}
else{
printf("false\n");
}
}
else if(_l && !_r){
max_rain = query(l+1, r);
if(max_rain < rain[l]){
printf("maybe\n");
}
else{
printf("false\n");
}
}
else{
max_rain = query(l+1, r-1);
if(max_rain < rain[r] && rain[r] <= rain[l]){
if(y-x == r-l){
printf("true\n");
}
else{
printf("maybe\n");
}
}
else{
printf("false\n");
}
}
}
}
线段树版本:
/**************************************************************
Problem: 1067
User: _ostreamBaba
Language: C++
Result: Accepted
Time:168 ms
Memory:2464 kb
****************************************************************/
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)
#define MOD 1000000007
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 50010;
using namespace std;
//#define TIME
inline int read(){
int x(0),f(1);
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int year[maxn];
int rain[maxn];
int N, M;
int sum[maxn<<2];
void PushUp(int rt)
{
sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
}
inline void buildTree(int l, int r, int rt)
{
if(l == r){
sum[rt] = rain[l];
return;
}
int m = (l + r) >> 1;
buildTree(lson);
buildTree(rson);
PushUp(rt);
}
inline int query(int L, int R, int l, int r, int rt)
{
if(L > R){
return -INF;
}
if(L <= l && r <= R){
return sum[rt];
}
int ret = 0;
int m = (l + r) >> 1;
if(L <= m){
ret = max(ret, query(L, R, lson));
}
if(R > m){
ret = max(ret, query(L, R, rson));
}
return ret;
}
inline int getpos(int p)
{
int pos = lower_bound(year+1, year+N+1, p)-year;
return pos;
}
int main()
{
// fin;
// fout;
mes(sum, 0);
N = read();
for(int i = 1; i <= N; ++i){
year[i] = read();
rain[i] = read();
}
buildTree(1, N, 1);
M = read();
while(M--){
int x, y, l, r, max_rain;
x = read();
y = read();
l = getpos(x);
r = getpos(y);
// cout << query(l, r, 1, N, 1) << endl;
bool _l = (l<=N&&year[l]==x); // find or no_find
bool _r = (r<=N&&year[r]==y); // find or no_find
if(_r == false){
--r;
}
if(_r && r == 1){
printf("maybe\n");
continue;
}
else if(_l && l == N){
printf("maybe\n");
continue;
}
if(!_l && !_r){
printf("maybe\n");
}
else if(!_l && _r){
max_rain = query(l, r-1, 1, N, 1);
if(max_rain < rain[r]){
printf("maybe\n");
}
else{
printf("false\n");
}
}
else if(_l && !_r){
max_rain = query(l+1, r, 1, N, 1);
if(max_rain < rain[l]){
printf("maybe\n");
}
else{
printf("false\n");
}
}
else{
max_rain = query(l+1, r-1, 1, N, 1);
if(max_rain < rain[r] && rain[r] <= rain[l]){
if(y-x == r-l){
printf("true\n");
}
else{
printf("maybe\n");
}
}
else{
printf("false\n");
}
}
}
}