P2471 [SCOI2007] 降雨量
P2471 [SCOI2007] 降雨量
题目翻译:
题目的意思是给你某些年的降雨量,在有\(n\)次查询,给定两个年份\(x,y\),问\(x\)年的降雨量是否是自\(y\)年以来最大的;
思路:
本题的时间过大,所以可以离散化。然后对于题目要求,是要求最大的,因此可以用线段树来维护区间最大值(因为是连续的,所以可以用其他算法)。而我们只需要找到在怎样的关系下为\(false,true,maybe\)
为\(false\)的情况:
1.当右端点年份确定,且中间年份最大降雨量大于等于右端点降雨量(中间有比它大的,所以他不是最大的)
2.当左端点年份确定,且中间年份最大降雨量大于等于左端点降雨量(题目要求,一定小于左端点的降雨量)
3.当左右端点年份都确定,且左端点降雨量小于等于右端点降雨量(题目要求的左端点的降雨量严格小于右端点,否则就应该是更前面的年份
为\(true\)的情况:
保证不为false情况后
1.当左右端点之差不等于左右端点年份之差(等价于年份不连续,也就是我前面所说的更好的判断区间连续的方法)2.左端点不确定
3.右端点不确定
为\(maybe\)的情况:
不满足以上所有即可
细节:
因为是用线段数组维护区间最大值,所以我们要保证查询时的点是之前存在的,因此我们只需要找到左右第一个存在的年份。再用线段树查询。因此最后要特判\(l\)和\(r\)是否为一个年份和\(l\)是否小于\(r\)
完整代码:
#include<bits/stdc++.h>
#define lc p<<1
#define rc p<<1|1
using namespace std;
const int N=5e4+5;
int tr[N*4],a[N];
map<int,int>t;
void build(int p,int l,int r){
if(l==r){
tr[p]=a[l];
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
tr[p]=max(tr[lc],tr[rc]);
}
int query(int p,int l,int r,int ll,int rr){
if(ll<=l && r<=rr)return tr[p];
int mid=(l+r)>>1;
int res=-2e9;
if(ll<=mid)res=max(res,query(lc,l,mid,ll,rr));
if(mid<rr)res=max(res,query(rc,mid+1,r,ll,rr));
return res;
}
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
int y,r;
cin>>y>>r;
a[i]=r;
t[y]=i;
}
build(1,1,n);
int m;
cin>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
if(x>=y){
cout<<"false"<<endl;
continue;
}
int l=x,r=y;
if(t[y]==0 && t[x]==0){
cout<<"maybe"<<endl;
continue;
}
while(t[l]==0)l++;
while(t[r]==0)r--;
if(l==r){
cout<<"maybe"<<endl;
continue;
}
int num=query(1,1,n,t[l]+int(t[x]!=0),t[r]-int(t[y]!=0));
if((t[y]!=0 && num>=a[t[y]]) || (t[x]!=0 && num>=a[t[x]]) || (t[x]!=0 && t[y]!=0 && a[t[x]]<=a[t[y]]))cout<<"false"<<endl;
else if(y-x!=t[y]-t[x] || t[x]==0 || t[y]==0)cout<<"maybe"<<endl;
else cout<<"true"<<endl;
}
}
本文作者:XichenOC
本文链接:https://www.cnblogs.com/XichenOC/p/18682340
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步