zoukankan      html  css  js  c++  java
  • 【题解】[SCOI2007]降雨量

    Problem

    ( ext{Solution:})

    Loj真好用)

    观察一下发现我们只需要简单维护区间最大值就可以了。但是如何判断 maybe 的情况?

    • 对于未知年份:

    考虑我们如果不知道一对已知年份中有没有未知年份,那一定有一个未知年份是和一个已知年份相邻的。

    所以,我们在离散化的时候将所有年份的左右相邻年份都加进去即可。(以防万一我加了相邻年份和相邻年份的相邻年份)

    这样我们就解决了未知年份的问题。

    • 对于判断是不是存在未知年份:

    考虑我们要将那些我们加进去的虚拟年份赋什么样的值。首先它一定不能影响到我们维护的正常最大值,所以我们可以考虑给它赋值一个无穷小,同时维护一下区间最小值。这样,每次查询一个 pair 维护两个值:最大值最小值,就可以判断了。

    • 对于三种情况的分类讨论:

    下面根据题目描述称年份 (y,x) .

    1. 两个年份的降雨量都知道:

    先判断 y 的降雨量是不是大于等于 x 的降雨量,不满足输出 false 。

    然后查询区间([y+1,x-1].) 如果存在最大值大于 x 的降雨量输出 false ,否则如果存在最小值是 -inf 输出 maybe ,其他情况是 true 。

    1. 知道 x 的降雨量,不知道 y 的降雨量。

    那就只有 false maybe 的判断了。只需要查询上述范围是不是有大于等于 x 降水量的年份即可。

    1. 两个年份的降雨量都不知道

    显然 maybe 。

    1. 知道 y 的降雨量,不知道 x 的降雨量

    这是一种比较隐蔽的情况,考虑会不会 false :

    我们查询区间中的最大值,如果最大值要大于 y 的降雨量,这说明 x 必然不能作为 y 年份后最大降雨量的年份,而是应当作为这个最大值所在的年份。

    否则输出 maybe 。

    空间计算

    由于离散化的时候我们建立的虚拟点比较多,所以空间需求自然要大。

    用了动态开点的线段树,所以空间应该开到两倍;同时计算节点个数约为 (5*5*10^4+10*10^4=3.5*10^5.)

    到了最后才发现 RE 的原因。以后空间问题一定要注意。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long 
    const int MAXN=2e6+10;
    const int inf=21474836470ll;
    int tot,n,m;
    int ls[MAXN],rs[MAXN],rt=1,val[MAXN];
    struct Tr{int l,r,maxn,minn;}tr[MAXN];
    struct Q{int y,x;}q[MAXN];
    struct N{int t,w;}a[MAXN];
    inline int Max(int x,int y){return x>y?x:y;}
    inline int Min(int x,int y){return x<y?x:y;}
    inline void pushup(int x){
    	tr[x].maxn=Max(tr[ls[x]].maxn,tr[rs[x]].maxn);
    	tr[x].minn=Min(tr[ls[x]].minn,tr[rs[x]].minn);
    }
    void build(int &x,int l,int r){
    	x=++tot;
    	tr[x].l=l;
    	tr[x].r=r;
    	if(l==r){
    		tr[x].maxn=val[l];
    		tr[x].minn=val[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls[x],l,mid);
    	build(rs[x],mid+1,r);
    	pushup(x);
    }
    pair<int,int>query(int x,int l,int r){
    	pair<int,int>Ans;
    	Ans.first=-inf;
    	Ans.second=inf;
    	if(tr[x].l>=l&&tr[x].r<=r){
    		return make_pair(tr[x].maxn,tr[x].minn);
    	}
    	int mid=(tr[x].l+tr[x].r)>>1;
    	if(l<=mid){
    		pair<int,int>Ask=query(ls[x],l,r);
    		if(Ans.first==-inf&&Ans.second==inf){
    			Ans=Ask;
    		}
    		else{
    			Ans.first=Max(Ans.first,Ask.first);
    			Ans.second=Min(Ans.second,Ask.second);
    		}
    	}
    	if(mid<r){
    		pair<int,int>Ask=query(rs[x],l,r);
    		if(Ans.first==-inf&&Ans.second==inf){
    			Ans=Ask;
    		}
    		else{
    			Ans.first=Max(Ans.first,Ask.first);
    			Ans.second=Min(Ans.second,Ask.second);
    		}
    	}
    	return Ans;
    }
    int b[MAXN],bcnt,blen;
    inline int getpos(int v){return lower_bound(b+1,b+blen+1,v)-b;}
    signed main(){
    	scanf("%lld",&n);
    	for(int i=1;i<=n;++i)scanf("%lld%lld",&a[i].t,&a[i].w),a[i].t+=1000000003;
    	for(int i=1;i<=n;++i){b[++bcnt]=a[i].t;b[++bcnt]=a[i].t+1;b[++bcnt]=a[i].t-1;b[++bcnt]=a[i].t+2;b[++bcnt]=a[i].t-2;}
    	scanf("%lld",&m);
    	for(int i=1;i<=m;++i){
    		int y,x;
    		scanf("%lld%lld",&y,&x);
    		y+=1000000003;
    		x+=1000000003;
    		b[++bcnt]=y;
    		b[++bcnt]=x;
    		b[++bcnt]=y+1;
    		b[++bcnt]=y-1;
    		b[++bcnt]=x+1;
    		b[++bcnt]=x-1; 
    		b[++bcnt]=x-2;
    		b[++bcnt]=x+2;
    		b[++bcnt]=y-2;
    		b[++bcnt]=y+2;
    		q[i]=(Q){y,x};
    	}
    	sort(b+1,b+bcnt+1);
    	blen=unique(b+1,b+bcnt+1)-b-1;
    	int mx=-1;
    	for(int i=1;i<=n;++i)a[i].t=getpos(a[i].t);
    	for(int i=1;i<=n;++i)mx=Max(mx,a[i].t);
    	for(int i=1;i<=mx+10;++i)val[i]=-inf;
    	for(int i=1;i<=n;++i)val[a[i].t]=a[i].w;
    	build(rt,1,mx+10);
    	for(int i=1;i<=m;++i){
    		int pre=q[i].y;
    		int now=q[i].x;
    		pre=getpos(pre);
    		now=getpos(now);
    		if(val[now]!=-inf&&val[pre]!=-inf){
    			if(val[pre]<val[now]){
    				puts("false");
    				continue;
    			}
    			pair<int,int>qq=query(rt,getpos(q[i].y+1),getpos(q[i].x-1));
    			if(qq.first>=val[now]){
    				puts("false");
    				continue;
    			}
    			if(qq.second==-inf){
    				puts("maybe");
    				continue;
    			}
    			puts("true");
    			continue;
    		}
    		if(val[now]!=-inf&&val[pre]==-inf){
    			pair<int,int>qq=query(rt,pre,getpos(q[i].x-1));
    			if(qq.first>=val[now]){
    				puts("false");
    				continue;
    			}
    			puts("maybe");
    			continue;
    		}
    		if(val[now]==-inf&&val[pre]==-inf){
    			puts("maybe");
    			continue;
    		}
    		if(val[now]==-inf&&val[pre]!=-inf){
    			pair<int,int>qq=query(rt,getpos(q[i].y+1),getpos(q[i].x-1));
    			if(qq.first>=val[pre]){
    				puts("false");
    				continue;
    			}
    			puts("maybe");
    			continue;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    jquery 异常
    easyui datagrid 单击行不选择行
    java 简单实现上传 | commons-fileupload
    abator ibatis 构建过程
    mysql 杂笔
    eclipse杂笔
    maven 构建项目
    ubuntu随笔
    powershell:convert-path
    maven学习笔记1
  • 原文地址:https://www.cnblogs.com/h-lka/p/14927611.html
Copyright © 2011-2022 走看看