P2471 [SCOI2007] 降雨量
[SCOI2007] 降雨量
题目描述
我们常常会说这样的话:“
输入格式
输入仅一行包含一个正整数
输出格式
对于每一个询问,输出 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
提示
数据保证
solution:
读题真的是非常重要的一个好习惯:“它的含义是
读懂了这句话之后这题就好办了,我们维护一个动态开点线段树支持单点插入和区间查询,并且无修改
设每年的降雨量为
然后我们对于每个询问(l,r)先查三个值:
w[l],w[r],和
那么一个询问的答案是ture的条件是:
如果满足前者但不满足后者,答案为maybe
如果l,r都不存在,那么显然是maybe
然后如果l,r有一个不存在并且存在的一方大于
如果上述条件都不成立,那么就是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; }