RT,ST表做的,样例过了,思路在代码下面
5RE 5WA Link
代码有不理解的地方请私信或者在下面 @ 鸽子。有QQ也可以QQ说
谢谢/qq
// Problem: P2471 [SCOI2007]降雨量
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2471
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define M 1000005
int n,m,flag,S,T,fk,ind,w[M],y[M];
int emp[M],lg[M],p2[M],ax[M][25],in[M][25];
struct node
{int dy,v;}dt[M];
map<int,int>val,id;
int main()
{
memset(in,0x3f3f3f3f,sizeof(in));
cin>>n; for(int i=0;i<=25;i++) p2[i]=pow(2,i); for(int i=0;i<=M-3;i++) lg[i]=log2(i);
for(int i=1;i<=n;i++) cin>>dt[i].dy>>dt[i].v,y[i]=dt[i].dy,w[i]=dt[i].v,id[dt[i].dy]=i,ax[i][0]=dt[i].v,val[dt[i].dy]=dt[i].v,emp[i]=(dt[i].dy-dt[i-1].dy==1?1:0),in[i-1][0]=emp[i]; cin>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=16;j++) ax[i][j]=max(ax[i][j-1],ax[i+p2[j-1]][j-1]);
for(int i=1;i<n;i++) for(int j=1;j<=16;j++) in[i][j]=min(in[i][j-1],in[i+p2[j-1]][j-1]);
while(m--)
{
cin>>S>>T,flag=0;
if(!id[T]) {cout<<"maybe"<<endl;continue;}
ind=lower_bound(y+1,y+1+n,S)-y,flag=(y[ind]!=S?1:0);
S=ind+1,T=id[T]-1,fk=lg[(T-S+1)];
ind=max(ax[S][fk],ax[T-p2[fk]+1][fk]);
S--,fk=lg[(T-S+1)];
flag=max(flag,min(in[S][fk],in[T-p2[fk]+1][fk])^1);
cout<<(ind>=w[T+1]?"false":(flag?"maybe":"true"))<<endl;
}
return 0;
}
/*
离散化,再用一个emp数组记录相邻两年是否相邻(?) ST维护区间min/max,
每次询问,二分一下找到L的位置,L的值没给就走到后驱,并且把flag标上
如果R的值没给,直接Maybe,否则,先查询emp的区间min,求出是否有空的年份,有的话flag标上
求降水量的区间max,如果max>=v[R],false,否则,如果flag=1,输出maybe,再否则就输出true
呜呜
*/