BZOJ 1067: [SCOI2007]降雨量(线段树/RMQ)

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。


题解:
题目已经说的很清楚要求区间最值了…就是判断条件时太恶心了…

解释写在代码里了


AC代码(线段树):

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 5e4+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
int n,Q,a[MAXN],y[MAXN];
struct node{ int l,r,val,mx; }t[MAXN<<2];
inline void pushup(int rt){
    t[rt].mx = max(t[rt<<1].mx,t[rt<<1|1].mx);
}
void build(int rt,int l,int r){
    t[rt].l=l,t[rt].r=r;
    if(l==r){ t[rt].val=t[rt].mx=a[l]; return; }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
    pushup(rt);
}
int query(int rt,int l,int r){
    if(l<=t[rt].l && t[rt].r<=r) return t[rt].mx;
    int mid = (t[rt].l+t[rt].r)>>1;
    if(r<=mid) return query(rt<<1,l,r);
    else if(l>mid) return query(rt<<1|1,l,r);
    else return max(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&y[i],&a[i]);
    build(1,1,n);
    scanf("%d",&Q);
    while(Q--){
        int yy,xx; scanf("%d%d",&yy,&xx);
        if(xx<=yy){ puts("false");continue; }
        int l = lower_bound(y+1,y+n+1,yy)-y;
        int r = lower_bound(y+1,y+n+1,xx)-y;
        bool fl = y[l]==yy,fr = y[r]==xx;//判断输入的两个年份是否为已知数值
        int ans = 0;
        if(l+(fl ? 1:0)<=r-1) ans=query(1,l+(fl ? 1:0),r-1);//[L+1,R-1]中间的最值
        if((fr && ans>=a[r]) || (fl && ans>=a[l]) || (fl && fr && (a[l]<a[r] || ans>=a[r])))
            puts("false");//输入年份已知降雨量才能判断
        //要满足x年的降雨量不超过y年,且中间年份的降雨量严格小于x年
        //x年的降雨量为a[r],y年则为a[l]
        else if(r-l != y[r]-y[l] || !fl || !fr) puts("maybe");
        //中间有不确定的年份,在没有false的情况下才能是maybe
        else puts("true");
    }
    return 0;
}

AC代码(RMQ):

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 5e4+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
int n,Q,a[MAXN],y[MAXN],dp[MAXN][20],lg[MAXN];
inline void RMQ(){
    for(int i=1;i<=n;i++) dp[i][0]=a[i];
    for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
inline int query(int l,int r){
    int k = lg[r-l+1];
    return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&y[i],&a[i]);
    RMQ();
    scanf("%d",&Q);
    while(Q--){
        int yy,xx; scanf("%d%d",&yy,&xx);
        if(xx<=yy){ puts("false");continue; }
        int l = lower_bound(y+1,y+n+1,yy)-y;
        int r = lower_bound(y+1,y+n+1,xx)-y;
        bool fl = y[l]==yy,fr = y[r]==xx;
        int ans = 0;
        if(l+(fl ? 1:0)<=r-1) ans=query(l+(fl ? 1:0),r-1);
        if((fr && ans>=a[r]) || (fl && ans>=a[l]) || (fl && fr && (a[l]<a[r] || ans>=a[r])))
            puts("false");
        else if(r-l != y[r]-y[l] || !fl || !fr) puts("maybe");
        else puts("true");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值