P2471 [SCOI2007]降雨量 https://www.luogu.com.cn/problem/P2471
明明是st表的题;
但是却在st表之外的细节地方花了好久时间orz;
关于st表的原理可以看这个:
算法学习笔记(12): ST表 - 知乎 (zhihu.com)
(或者自己把st表什么的打印一下看看就明白了)
题意:求 x 是自从 y 以来 降水量最多的年份 这句话对不对
思路:
输入(年份) y 和 x ;
1.假如y和x的降水量都不知道——maybe;
2.假如y降水量不知道,x降水量知道:
——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量—— 若有,false;若无,maybe;
3.假如y降水量知道,x降水量不知道:
——查询y到x之间 有无 年份z的降水量 大于或等于 y的降水量—— 若有,false;若无,maybe;
4.假如y和x的降水量都知道:
(0)若y的降水量大于x的降水量——false;
(1)y到x之间所有年份的降水量都已知:
——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量
——若有,false;若无,true;
(2)y到x之间有年份的降水量未知:
——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量
——若有,false;若无,maybe;
以上是判断条件;
那么问题是:怎么判断y和x之间有没有未知年份??
年份x,y的数据范围是,所以就离散化了;
【用vis数组看这一年有没有降水量可能MLE先不说,好像也不能一下子看出来中间有没有年份降水量是0,暴力会TLE】
方法一vector(没试过,摊):
考虑用 vector[第几个]=年份 的方法,年份的降水量是st表中的 st[i][0] ;
看yx年份有没有降水量——用vector+lower_bound看找到的年份是不是xy的;
看yx中间年份有没有降水量——看xy的年份差是否等于xy的序号差;
查中间最值——用lower_bound找好后直接st表查;
方法二map(代码如下):
考虑用 map[年份]=第几个 的方法,年份的降水量是st表中的 st[i][0] ;
看yx年份有没有降水量——用map[年份]是否为0 看或者用count看;
看yx中间年份有没有降水量——看xy的年份差是否等于xy的序号差;
查中间最值——用lower_bound找好后直接st表查;
代码如下:
注意:
low_bound找到end的地方要判断一下!
st表查询时x-1到y+1之间的判断!如果x-1==y,那么中间值就是0!
找年份的时候,low_bound是找不小于这个年份的!!
#include<bits/stdc++.h>
using namespace std;
inline int read() {
char c=getchar();
int x=0,f=1;
while (c<'0'||c>'9'){
if (c=='-') f=-1;
c=getchar();
}
while (c >='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int lg[50006];
int f[50006][20],q;
map <int,int> mp;
int query(int x, int y) {
int l=lg[y-x+1];
return max(f[x][l],f[y-(1<<l)+1][l]);
}
int main()
{
int n;n=read();
lg[1]=0;
for (int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
for (int i=1;i<=n;i++){int x;x=read();mp[x]=i;f[i][0]=read();}
for (int j=1;j<=lg[n];j++)
for (int i=1;i<=n-(1<<j)+1;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int m;
m=read();
while(m--){
int x,y;
scanf("%d%d",&y,&x);//year
if(y>=x){puts("false");continue;}
if(!mp.count(y)&&!mp.count(x)){puts("maybe");continue;}
map<int,int>::iterator itx=mp.lower_bound(x),ity=mp.lower_bound(y);
if(!mp.count(y)&&mp.count(x))
{
int numy=ity->second;
int q=numy<=mp[x]-1?query(numy,mp[x]-1):0;
if(q>=f[mp[x]][0]){puts("false");continue;}
else {puts("maybe");continue;}
}
if(mp.count(y)&&!mp.count(x))
{
int numx=itx==mp.end()?mp.size():itx->second-1;
int q=mp[y]+1<=numx?query(mp[y]+1,numx):0;
if(q>=f[mp[y]][0]){puts("false");continue;}
else {puts("maybe");
continue;}
}
if(f[mp[x]][0]>f[mp[y]][0]){puts("false");continue;}
if(y-x==mp[y]-mp[x])
{
int q=mp[y]+1<=mp[x]-1?query(mp[y]+1,mp[x]-1):0;
if(q>=f[mp[x]][0]){puts("false");continue;}
else {puts("true");continue;}
}
else {
int q=mp[y]+1<=mp[x]-1?query(mp[y]+1,mp[x]-1):0;
if(q>=f[mp[x]][0]){puts("false");continue;}
else {puts("maybe");continue;}
}
}
return 0;
}