BZOJ 1067: [SCOI2007]降雨量

1067: [SCOI2007]降雨量

Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 5079 Solved: 1345
[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

之前以为这是一道傻逼线段树的题,维护最大值,再用一个flag维护中间是否有间隔的年份。后来发现自己想多了。其实RMQ就可以搞定最大值,判断序号的差和实际的年份的差是不是一样的就可以判断是否有间隔年了。
然后交上去就WA了。我果然还是too naive了。
这道题太恶心了我的大半个上午啊,各种取等条件。
各种情况:
1.y年比x年大。这个肯定是false
2.y年跟x一样 应该是没有这个点的23333个人感觉应该是false
2.y年和x年有不存的情况
(1)都不存在 maybe
(2)两者中有一个不存在。如果在区间[x+1,y-1]中,所有的年份都小于x年或y年的降水量 则是maybe,否则是false
3.两者都存在。
(1)严格满足题意,y年降水量小于等于x年且y年降水量比[x+1,y-1]中的最大值大,且中间没有间隔年 返回true (唯一返回true)
(2)除了中间没有间隔年外其他和上述1一样 返回maybe
(3)这个的其他情况 返回false
大概是这样。心累。
这道题是来考耐心的吧QAQ

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<map>
using namespace std;

const int N = 100010;

int n,m;
int a[N],b[N],c[N];

inline int Max(int a,int b){
    return a>b?a:b;
}

struct node{
    int mmax,year;
    int l,r; 
}t[N<<1];

void build(int root,int l,int r){
    t[root].l=l,t[root].r=r;
    if(l==r){
        t[root].mmax=b[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    t[root].mmax=Max(t[root<<1].mmax,t[root<<1|1].mmax);
}

int query(int root,int pos,int val){
    int l=t[root].l,r=t[root].r;
    if(pos<=l&&val>=r) return t[root].mmax;
    int ans=-1;
    int mid=(l+r)>>1;
    if(pos<=mid) ans=Max(ans,query(root<<1,pos,val));
    if(val>mid) ans=Max(ans,query(root<<1|1,pos,val));
    return ans;
}

int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&b[i]);
    scanf("%d",&m);
    build(1,1,n);
    while(m--){
        int aa,bb;
        scanf("%d%d",&aa,&bb);
        if(aa>bb) {printf("false\n");continue;}//a年大于b年
    //  if(aa==bb) {printf("maybe\n");continue;}
        int x=upper_bound(a+1,a+n+1,aa)-a-1; 
        int y=upper_bound(a+1,a+n+1,bb)-a-1;
        if(a[x]!=aa&&a[y]!=bb) {printf("maybe\n");continue;}//两个年份都不存在
        if(x==n) {printf("maybe\n");continue;}//a为年份最大的一年 
        if(y<=1) {printf("maybe\n");continue;}//b为年份最小的一年 
        if(a[x]!=aa){//a年不存在 b年存在 
            int mmax=query(1,x+1,y-1);
            if(mmax>=b[y]) printf("false\n");//中间有比b年大的 
            else printf("maybe\n");//中间没有比b年大的 
            continue;
        }
        if(a[y]!=bb){//b年不存在
            int mmax=query(1,x+1,y); 
            if(mmax>=b[x]) printf("false\n");//有比a年大的 
            else printf("maybe\n");
            continue;//中间没有比b年大的 
        }
        //a、b都存在
        int mmax=query(1,x+1,y-1);
        if(mmax<b[y]&&b[y]<=b[x]){
             if(bb-aa==y-x) printf("true\n");
             else printf("maybe\n");
             continue;
        }
        printf("false\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值