Description
我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意
Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,
则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未
知,有的说法是可能正确也可以不正确的。
Input
输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小
到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是
自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。
Output
对于每一个询问,输出true,false或者maybe。
题解:
题目已经说的很清楚要求区间最值了…就是判断条件时太恶心了…
解释写在代码里了
AC代码(线段树):
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 5e4+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
int n,Q,a[MAXN],y[MAXN];
struct node{ int l,r,val,mx; }t[MAXN<<2];
inline void pushup(int rt){
t[rt].mx = max(t[rt<<1].mx,t[rt<<1|1].mx);
}
void build(int rt,int l,int r){
t[rt].l=l,t[rt].r=r;
if(l==r){ t[rt].val=t[rt].mx=a[l]; return; }
int mid=(l+r)>>1;
build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
pushup(rt);
}
int query(int rt,int l,int r){
if(l<=t[rt].l && t[rt].r<=r) return t[rt].mx;
int mid = (t[rt].l+t[rt].r)>>1;
if(r<=mid) return query(rt<<1,l,r);
else if(l>mid) return query(rt<<1|1,l,r);
else return max(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&y[i],&a[i]);
build(1,1,n);
scanf("%d",&Q);
while(Q--){
int yy,xx; scanf("%d%d",&yy,&xx);
if(xx<=yy){ puts("false");continue; }
int l = lower_bound(y+1,y+n+1,yy)-y;
int r = lower_bound(y+1,y+n+1,xx)-y;
bool fl = y[l]==yy,fr = y[r]==xx;//判断输入的两个年份是否为已知数值
int ans = 0;
if(l+(fl ? 1:0)<=r-1) ans=query(1,l+(fl ? 1:0),r-1);//[L+1,R-1]中间的最值
if((fr && ans>=a[r]) || (fl && ans>=a[l]) || (fl && fr && (a[l]<a[r] || ans>=a[r])))
puts("false");//输入年份已知降雨量才能判断
//要满足x年的降雨量不超过y年,且中间年份的降雨量严格小于x年
//x年的降雨量为a[r],y年则为a[l]
else if(r-l != y[r]-y[l] || !fl || !fr) puts("maybe");
//中间有不确定的年份,在没有false的情况下才能是maybe
else puts("true");
}
return 0;
}
AC代码(RMQ):
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 5e4+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
int n,Q,a[MAXN],y[MAXN],dp[MAXN][20],lg[MAXN];
inline void RMQ(){
for(int i=1;i<=n;i++) dp[i][0]=a[i];
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
inline int query(int l,int r){
int k = lg[r-l+1];
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&y[i],&a[i]);
RMQ();
scanf("%d",&Q);
while(Q--){
int yy,xx; scanf("%d%d",&yy,&xx);
if(xx<=yy){ puts("false");continue; }
int l = lower_bound(y+1,y+n+1,yy)-y;
int r = lower_bound(y+1,y+n+1,xx)-y;
bool fl = y[l]==yy,fr = y[r]==xx;
int ans = 0;
if(l+(fl ? 1:0)<=r-1) ans=query(l+(fl ? 1:0),r-1);
if((fr && ans>=a[r]) || (fl && ans>=a[l]) || (fl && fr && (a[l]<a[r] || ans>=a[r])))
puts("false");
else if(r-l != y[r]-y[l] || !fl || !fr) puts("maybe");
else puts("true");
}
return 0;
}
来源:CSDN
作者:Nightmare丶
链接:https://blog.csdn.net/qq_43544481/article/details/103782941