降雨量 2007年省队选拔赛四川
时间限制: 1 s
空间限制: 64000 KB
题目等级 : 大师 Master
题解
查看运行结果
题目描述 Description
我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。
输入描述 Input Description
输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。
输出描述 Output Description
对于每一个询问,输出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
数据范围及提示 Data Size & Hint
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9
写在前面:改代码改了一个多小时,一遍90呵呵呵
——————————————————————————————————————————————
思路:
就是一个最值线段树加二分查找位置,但是分类的情况太过繁琐,不想手打了,直接搬运黄学长的blog
需要考虑很多情况。比如第x年到第y年
如果y<x,不知道有没这种情况,应该是false吧
true的情况需要满足
x与y的值都已知且y值<x值且x+1到y-1都已知并且都小于y值
maybe满足
1.x值y值均未知
2.已知x值未知y值并且x+1到y-1都已知并且都小于y值
3.已知y值未知x值并且x+1到y-1都已知并且都小于x值
4.x为年份最大一年,y>x
5.y为年份最小一年,x<y{当时我就是忘了这两点,导致一直90,OTZ}
6.x,y均已知且y<x并且x+1到y-1有未知并且都小于x值
其它都是false
大概这样。。。
这种题一遍AC的是神
*调了几个小时
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,x,y,tot,pos1,pos2;
struct os
{
int year,rain;
}a[50010],tree[200010],k;
bool flag_x,flag_y;
os maxx(os x,os y)
{
if (x.rain>y.rain) return x;
else return y;
}
void build(int root,int begin,int end)
{
if (begin==end) {tree[root]=a[begin];return;}
int mid=(begin+end)/2;
build(root*2,begin,mid);
build(root*2+1,mid+1,end);
tree[root]=maxx(tree[root*2],tree[root*2+1]);
}
os get(int root,int begin,int end,int l,int r)
{
if (begin==end) return tree[root];
if (l<=begin&&r>=end) return tree[root];
int mid=(begin+end)/2;
os ans1,ans2;
ans2.rain=ans1.rain=0;
if (mid>=l) ans1=get(root*2,begin,mid,l,r);
if (mid<r) ans2=get(root*2+1,mid+1,end,l,r);
return maxx(ans1,ans2);
}
int find1(int x)
{
int l=1,r=n,mid=(l+r)/2;
while (l<r)
{
if (a[mid].year==x) return mid;
if (a[mid].year>x) r=mid-1,mid=(l+r)/2;
if (a[mid].year<x) l=mid+1,mid=(l+r)/2;
}
if (a[mid].year==x) return mid;
flag_x=0;
while (a[mid].year>x&&mid>1) mid--;
return mid;
}
int find2(int x)
{
int l=1,r=n,mid=(l+r)/2;
while (l<r)
{
if (a[mid].year==x) return mid;
if (a[mid].year>x) r=mid-1,mid=(l+r)/2;
if (a[mid].year<x) l=mid+1,mid=(l+r)/2;
}
if (a[mid].year==x) return mid;
flag_y=0;
while (a[mid].year<x&&mid<n) mid++;
return mid;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d%d",&a[i].year,&a[i].rain);
build(1,1,n);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&y,&x);
flag_x=flag_y=1;
pos1=find1(x),pos2=find2(y);
int l=pos2,r=pos1;
if (flag_y) l++;
if (flag_x) r--;
if (!flag_y&&!flag_x) {printf("maybe\n");continue;}
if (flag_y&&flag_x&&a[pos1].rain>a[pos2].rain) {printf("false\n");continue;}
if ((pos1==1&&!flag_y)||(pos2==n&&!flag_x)) {printf("maybe\n");continue;}
k=get(1,1,n,l,r);
if (!flag_x&&flag_y)
{
if (a[pos1].rain<=k.rain&&a[pos2].rain<=k.rain) {printf("false\n");continue;}
else
{printf("maybe\n");continue;}
}
if (flag_x&&!flag_y)
{
if (a[pos1].rain<=k.rain) {printf("false\n");continue;}
else {printf("maybe\n");continue;}
}
if (flag_x&&flag_y)
if (a[pos1].rain>k.rain)
if (pos1-pos2==x-y){printf("true\n");continue;}
else {printf("maybe\n");continue;}
else {printf("false\n");continue;}
}
}