bzoj 1067: [SCOI2007]降雨量

题目链接:

bzoj 1067: [SCOI2007]降雨量

题解:

很简单的一道题,但代码里有许多细节需要注意,切容易出错,调了三个小时OTZ
做一个st表维护区间最大值就
在获得年份在序列中的pos时二分
也可以维护平衡树查询pos
或者用直接用线段维护最大值同时维护区间中有多少年份
其次分情况讨论就好了

#include<cmath>
#include<cstdio>
#include<algorithm>
inline int read() {
    int x=0,f=1;
    char c=getchar() ;
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
    return x*f;
}
const int maxn = 50007;
int a[maxn],b[maxn];int f[maxn][21],n;
void make_st() {
    for(int i=1;i<=20;++i) 
        for(int j=1;j+(1<<i)-1<=n;++j) 
            f[j][i]=std::max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
}
int query(int l,int r) {
    if (l>r)  
        return-0x7fffffff;  
    int q=log(r-l+1)/log(2);
    return std::max(f[l][q],f[r-(1<<q)+1][q]);
}
int getpos(int f) {
    int l=1,r=n,ret=0;
    while(l<=r) {
        int mid=l+r>>1;
        if(a[mid]<=f)ret=mid,l=mid+1;
        else r=mid-1;
    }
        return ret;
}
int main() {
    n=read();
    for(int i=1;i<=n;++i) {
        a[i]=read(),b[i]=read();f[i][0]=b[i];
    }
    make_st();
    int m=read() ;
    for(int a1,b1;m--;) {
        a1=read() ,b1=read();
        int pa=getpos(a1),pb=getpos(b1);
        if(a[pa]!=a1&&a[pb]!=b1) {puts("maybe");continue;}
        if(a[pa]!=a1&&a[pb]==b1) {
            if(query(pa+1,pb-1)<b[pb])puts("maybe");
            else puts("false");continue;
        }
        if(a[pa]==a1&&a[pb]!=b1) {
            if(query(pa+1,pb)<b[pa])puts("maybe");
            else puts("false");continue;
        }
        if(pb-pa!=b1-a1) {
            if(query(pa+1,pb-1)>=b[pb]||b[pb]>=b[pa]) puts("false");
            else puts("maybe");continue;
        }
        if(query(pa+1,pb-1)<b[pb]&&b[pa]>b[pb]) puts("true");
        else puts("false");
        //printf("max(pa -> pb) : %d\n",query(pa+1,pb));
    }
    return 0;
}

转载于:https://www.cnblogs.com/sssy/p/8457150.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值