P2471 [SCOI2007] 降雨量

liuboom發表於2024-11-11

[SCOI2007] 降雨量

題目描述

我們常常會說這樣的話:“\(X\) 年是自 \(Y\) 年以來降雨量最多的”。它的含義是 \(X\) 年的降雨量不超過 \(Y\) 年,且對於任意 \(Y < Z < X\)\(Z\) 年的降雨量嚴格小於 \(X\) 年。例如 2002、2003、2004 和 2005 年的降雨量分別為 \(4920\)\(5901\)\(2832\)\(3890\),則可以說“2005 年是自 2003 年以來最多的”,但不能說“2005 年是自 2002 年以來最多的”由於有些年份的降雨量未知,有的說法是可能正確也可以不正確的。

輸入格式

輸入僅一行包含一個正整數 \(n\),為已知的資料。以下 \(n\) 行每行兩個整數 \(y_i\)\(r_i\),為年份和降雨量,按照年份從小到大排列,即 \(y_i<y_{i+1}\)。下一行包含一個正整數 \(m\),為詢問的次數。以下 \(m\) 行每行包含兩個數 \(Y\)\(X\),即詢問“\(X\) 年是自 \(Y\) 年以來降雨量最多的。”這句話是“必真”、“必假”還是“有可能”。

輸出格式

對於每一個詢問,輸出 truefalse 或者 maybe

樣例 #1

樣例輸入 #1

6
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008

樣例輸出 #1

false
true
false
maybe
false

提示

\(100 \%\) 的資料滿足:\(1 \le n \le 50000\)\(1 \le m \le 10000\)\(-10^9 \le y_i \le 10^9\)\(1 \le r_i \le 10^9\)\(-10^9 \le X, Y \le 10^9\)

資料保證 \(Y < X\)

solution:

讀題真的是非常重要的一個好習慣:“它的含義是 \(X\) 年的降雨量不超過 \(Y\) 年,且對於任意 \(Y < Z < X\)\(Z\) 年的降雨量嚴格小於 \(X\) 年。”

讀懂了這句話之後這題就好辦了,我們維護一個動態開點線段樹支援單點插入和區間查詢,並且無修改

設每年的降雨量為\(w_i\)
然後我們對於每個詢問(l,r)先查三個值:
w[l],w[r],和\(\forall i \in[l+1,r-1],\max w\)
那麼一個詢問的答案是ture的條件是:\(w[l] \ge w[r] > \max w\)且[l+1,r]是滿的
如果滿足前者但不滿足後者,答案為maybe
如果l,r都不存在,那麼顯然是maybe
然後如果l,r有一個不存在並且存在的一方大於\(\max w\):也是maybe
如果上述條件都不成立,那麼就是false了

Code:

#include<bits/stdc++.h>
const int N=1e5+5;
const int inf=1e9;
using namespace std;
map<int,int> Map;
int n,m,cnt,rt;
//Segment_Tree
struct Segment_Tree{
    int ls,rs,val,cnt;
}t[N*40];
void pushup(int x)
{
    t[x].val=max(t[t[x].ls].val,t[t[x].rs].val);
    t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt;
}
void insert(int &x,int y,int l,int r,int pos,int val)
{
    t[x=++cnt]=t[y];
    if(l==r)
    {
        t[x].val=val;
        t[x].cnt=1;
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid)insert(t[x].ls,t[y].ls,l,mid,pos,val);
    if(mid<pos)insert(t[x].rs,t[y].rs,mid+1,r,pos,val);
    pushup(x);
}
void query(int x,int l,int r,int L,int R,int &res,int &tot)
{
    if(!x)return;
    if(L<=l&&r<=R)
    {
        res=max(res,t[x].val);
        tot+=t[x].cnt;
        return ;
    }
    int mid=l+r>>1;
    if(L<=mid)query(t[x].ls,l,mid,L,R,res,tot);
    if(mid<R)query(t[x].rs,mid+1,r,L,R,res,tot);
}
void work()
{
    cin>>n;
    for(int i=1,t,w;i<=n;i++)
    {
        scanf("%d%d",&t,&w);
        insert(rt,rt,-inf,inf,t,w);
        Map[t]=w;
    }
    cin>>m;
    for(int i=1,l,r;i<=m;i++)
    {
        scanf("%d%d",&l,&r);
        int pre=0,mid=0,ans=0,tot=0;
        if(l+1<=r-1)
        query(rt,-inf,inf,l+1,r-1,mid,tot);
        tot=0;
        query(rt,-inf,inf,l+1,r,ans,tot);
        if(Map[l]>=Map[r]&&mid<Map[r]&&tot<r-l){printf("maybe\n");continue;}
        if(Map[l]>=Map[r]&&mid<Map[r]){printf("true\n");continue;}
        if(!Map[l]&&!Map[r]){printf("maybe\n");continue;}
        if(!Map[l]&&Map[r]>mid){printf("maybe\n");continue;}
        if(!Map[r]&&Map[l]>mid){printf("maybe\n");continue;}
        printf("false\n");
    }
}
int main()
{
    //freopen("P2471_1.in","r",stdin);
    //freopen("P2471.out","w",stdout);
    work();
    return 0;
}