【SCOI2007】【BZOJ1067】【codevs2439】降雨量,分类讨论の线段树

降雨量 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;}
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值