洛谷 P2471 [SCOI2007]降雨量

题目链接

在神贴题单里看到了这道题,就拿出来做了。

神贴链接

推荐看看这个洛谷神贴题单,真的很好笑

题目思路比较明显对,年份离散化,年份也是单调递增的。很明显,我们

是需要维护年份区间最大的,可以利用线段树或者st表维护,针对每一组

询问,我们由已知条件来分类讨论即可,分类讨论比较复杂,需要注意细

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1e5;
inline int read(){
	int ret=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-f;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0'){
		ret=ret*10+(ch^'0');
		ch=getchar();
	}
	return f*ret;
}
int n,m;
int a[maxn];
int v[maxn];
struct node{
	int val;
}tre[maxn*4];
void build(int rt,int l,int r){
	if(l==r){
		tre[rt].val=v[l];
		return;
	}
	int mid=(l+r)>>1;
	build(rt*2,l,mid);
	build(rt*2+1,mid+1,r);
	tre[rt].val=max(tre[rt*2].val,tre[rt*2+1].val);
}
int query(int rt,int l,int r,int ql,int qr){
	if(l>qr||r<ql){
		return 0 ;
	}
	if(l>=ql&&r<=qr){
		return tre[rt].val;
	}
	int mid=(l+r)>>1;
	int ans=-1;
	if(ql<=mid){
		ans=max(ans,query(rt*2,l,mid,ql,qr));
	}
	if(qr>mid){
		ans=max(ans,query(rt*2+1,mid+1,r,ql,qr));
	}
	return ans;
}
int main(){
	freopen("a.in","r",stdin);
	n=read();
//	cout<<n<<endl;
	for(int i=1;i<=n;i++){
		a[i]=read();
		v[i]=read(); 
	}
	build(1,1,n);
	m=read();
	int ye;
	int val;
	int st=0,la=0;
	int stt;
	int laa; 
	for(int i=1;i<=m;i++){
		stt=read();
		laa=read();//获得年份 a,b; 
		st=lower_bound(a+1,a+1+n,stt)-a;//在年份表内查找出对应年份的下标 
		la=lower_bound(a+1,a+1+n,laa)-a;
		int le=laa-stt+1;
		int f1=0;
		int f2=0;
		int maxx=-1;
		if(a[st]!=stt){//过没查到,就是没有该元素 
			f1=1;//做标记 
		}
		if(a[la]!=laa){
			f2=1;
		}
		if(f1&&f2){//如果两个元素都没有 
			cout<<"maybe"<<endl;//无法确定判断是否正确 
			continue;
		}
		if(!f1&&!f2){//如果两个年份都有 
			if(v[st]<=v[la]){//如果 b年的降雨量大于等于a的,错误 
				cout<<"false"<<endl;
				continue;
			}
			int len=laa-stt;//求出实际年份差
			if(len==1){//假设两年的实际差值为一 
				if(v[la]<v[st]){
					cout<<"true"<<endl;//如果b年小于a年符合题意 
				}
				else {
					cout<<"false"<<endl; 
				}
				continue;
			} 
			if(la-st==1){//如果两年内部年份全部未知 
				cout<<"maybe"<<endl;
				continue;
			}
			maxx=query(1,1,n,st+1,la-1); 
			if(maxx>=v[la]){//a,b年份内已知区间内出现最大年份大于b 
				cout<<"false"<<endl;
				continue;
			}
			else{
				if(le==la-st+1)
					cout<<"true"<<endl;
				else{
					cout<<"maybe"<<endl;
				}
				continue;
			}
		}
		if(f1&&!f2){//如果a未知,b已知 
			if(st==la){//如果区间内全未知 
				cout<<"maybe"<<endl;
				continue;
			}
			maxx=query(1,1,n,st,la-1);
			if(maxx>=v[la]){
				cout<<"false"<<endl;
			}
			else
				cout<<"maybe"<<endl;//由于我们不知道A,所以无法确定 
			continue;
		}
		if(!f1&&f2){//第一个已知,第二个未知 
			if(la-1==st){//如果询问区间全未知 
				cout<<"maybe"<<endl;
				continue;
			}
			maxx=query(1,1,n,st+1,la-1);
			if(maxx>=v[st]){
				cout<<"false"<<endl;
			}
			else{
				cout<<"maybe"<<endl;
			}
			continue;
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/rpup/p/14026890.html