降雨量

发布时间 2023-09-25 20:27:40作者: wscqwq

P2471 [SCOI2007] 降雨量

这题的核心不是 ST 表,而是讨论。

大体思路

我们先找 \(Y,X\) 两个位置(不太习惯,下面用 \(A,B\) 表示),记录是否确定值。

接着找 \((A,B)\) 区间内确定值的位置,做一次查询最大值。

接下来就是分类了:

  1. false
    1. 如果 \(A,B\) 确定,并且 \(W_B>W_A\)\(W\) 表示降水量)。
    2. 中间有值,并且 \(A\) 确定,\(B\) 不确定,中间最大值不小于 \(A\),那么可以推断出 \(B\) 不可能作为最大值(因为它的值一定不超过 \(A\))。
    3. 中间的值不小于 \(W_B\)
  2. true:\(A,B\) 确定,中间要么没有,要么中间的值都是确定的,并且最大值小于 \(W_B\)
  3. maybe:其余情况都是。

维护最值个人喜欢用 ST 表,原因是不容易打挂,而且查询复杂度小,代码短,完全优于线段树。

#include<cstdio>
#include<algorithm>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
const int N=50010,INF=2e9,M=16;
int n,y[N],w[N],m,f[M][N],LOG[N];//y年份 r雨量
void RMQ(){
    E(i, n)f[0][i]=w[i];
    E(i, LOG[n]){
        for(int j=1;j+(1<<i)-1<=n;++j)
            f[i][j]=max(f[i-1][j],f[i-1][j+(1<<i-1)]);
    }
}
int find(int x){//>=x的第一个位置
    int l=1,r=n+1;
    Wh(l<r){
        int mid=l+r>>1;
        if(y[mid]>=x)r=mid;
        else l=mid+1;
    }
    return l;
}
int Find(int x){//<=x的最后一个位置
    int l=0,r=n;
    Wh(l<r){
        int mid=l+r+1>>1;
        if(y[mid]<=x)l=mid;
        else r=mid-1;
    }
    return l;
}
int query(int l,int R){
    if(l>R)return -INF;
    int k=LOG[R-l+1];
    return max(f[k][l],f[k][R-(1<<k)+1]);
    // int maxn=0;
    // Le(i, l, R)
    //     maxn=max(w[i],maxn);
    // return maxn;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d",&n);
    LOG[1]=0;
    Le(i, 2, n)LOG[i]=LOG[i>>1]+1;
    E(i, n)scanf("%d%d",y+i,w+i);
    y[0]=-INF;
    y[n+1]=INF;
    RMQ();
    scanf("%d",&m);
    E(i, m){
        int a,b;
        scanf("%d%d",&a,&b);
        int BP=find(b),AP=find(a);
        bool HB=y[BP]==b,HA=y[AP]==a;
        int posa=find(a+1),posb=Find(b-1);
        bool Hmid=a+1<=b-1;
        int tmp=query(posa,posb);
        //false
        if(HA&&HB&&w[AP]<w[BP]||Hmid&&HA&&!HB&&tmp>=w[AP]||Hmid&&HB&&tmp>=w[BP])
            puts("false");
        else if(HA&&HB&&(!Hmid||posb-posa+1==b-a-1&&tmp<w[BP]))
            puts("true");
        else
            puts("maybe");
    }
    return 0;
}