[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\) 年以來降雨量最多的。”這句話是“必真”、“必假”還是“有可能”。
輸出格式
對於每一個詢問,輸出 true
、false
或者 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;
}