BZOJ 1067[SCOI 2007]
2016-03-26 21:22
344 查看
1067: [SCOI2007]降雨量
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3301 Solved: 850
[Submit][Status][Discuss]
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。Sample Input
62002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008
Sample Output
falsetrue
false
maybe
false
HINT
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9看到这么大的数据,就可以非常显然的想到是线段树,但是本题有非常多的限制和判断:
true的情况需要满足
x与y的值都已知且y值<x值且x+1到y-1都已知并且都小于y值
maybe满足
1.x值y值均未知
2.已知x值未知y值并且x+1到y-1都已知并且都小于y值
3.已知y值未知x值并且x+1到y-1都已知并且都小于x值
4.x为年份最大一年,y>x
5.y为年份最小一年,x<y
6.x,y均已知且y<x并且x+1到y-1有未知并且都小于x值
其它都是false(源自:http://hzwer.com/1655.html)
下面是代码;
#include<cstdio> #include<iostream> using namespace std; struct d 4000 ata{int ly,ry,mx,know;}tr[200001];//ly,ry是线段树维护的范围 //mx表示从ly到ry年中降雨量的最大值,know表示从ly到ry年的降雨量是否都知道 int n,m; void build(int k,int l,int r)//建树 { if(l==r) { scanf("%d%d",&tr[k].ly,&tr[k].mx); tr[k].ry=tr[k].ly; tr[k].know=1; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tr[k].know=(tr[k<<1].know && tr[k<<1|1].know); if(tr[k<<1].ry+1!=tr[k<<1|1].ly)tr[k].know=0; tr[k].ly=tr[k<<1].ly; tr[k].ry=tr[k<<1|1].ry; tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx); } int get(int k,int x)//找到x年的降雨量 { if(tr[k].ly==tr[k].ry) { if(tr[k].ly!=x)return 0; else return tr[k].mx; } if(tr[k<<1].ry>=x)return get(k<<1,x); else if(tr[k<<1|1].ly<=x)return get(k<<1|1,x); return 0; } int getnext(int k,int x) { int l=tr[k].ly,r=tr[k].ry; if(l==r)return tr[k].ly; if(x<tr[k<<1].ry)return getnext(k<<1,x); else return getnext(k<<1|1,x); } int getlast(int k,int x) { int l=tr[k].ly,r=tr[k].ry; if(l==r)return tr[k].ly; if(x>tr[k<<1|1].ly)return getlast(k<<1|1,x); else return getlast(k<<1,x); } int ask(int k,int x,int y,int num)//判断是否有哪一年的降雨量大于需要判断的年份 { bool f=0; if(x<tr[k].ly){f=1;x=tr[k].ly;} if(tr[k].ly==x&&tr[k].ry==y) { if(tr[k].mx>=num)return 0; else if(tr[k].know&&!f)return 1; else return 2; } if(y<=tr[k<<1].ry) return ask(k<<1,x,y,num); else if(x>=tr[k<<1|1].ly) return ask(k<<1|1,x,y,num); else { int t1=ask(k<<1,x,tr[k<<1].ry,num); int t2=ask(k<<1|1,tr[k<<1|1].ly,y,num); if(!t1||!t2)return 0; else if(tr[k<<1].ry+1!=tr[k<<1|1].ly)return 2; else return 1; } } int main() { int n; scanf("%d",&n); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { int l,r; scanf("%d%d",&l,&r); if(r<l){printf("false\n");continue;} int lnum=get(1,l),rnum=get(1,r); if(!lnum && !rnum)printf("maybe\n"); else { int s=getnext(1,l),t=getlast(1,r); if(!lnum) { if(s>t||r==t){printf("maybe\n");continue;} int f=ask(1,s,t,rnum); if(f==0)printf("false\n"); else printf("maybe\n"); } else if(!rnum) { if(s>t||l==s){printf("maybe\n");continue;} int f=ask(1,s,t,lnum); if(f==0)printf("false\n"); else printf("maybe\n"); } else { if(rnum>lnum){printf("false\n");continue;} if(s>t) { if(l+1==r)printf("true\n"); else printf("maybe\n"); continue; } int f=ask(1,s,t,rnum); if(f==0)printf("false\n"); else if(f==1) { if(l+1==s&&r-1==t)printf("true\n"); else printf("maybe\n"); } else if(ask(1,s,t,rnum)==2)printf("maybe\n"); else printf("false\n"); } } } return 0; }
相关文章推荐
- 新注册
- 四大漏洞入侵博客
- 在Ubuntu系统上安装Ghost博客平台的教程
- PHP多用户博客系统分析[想做多用户博客的朋友,需要了解]第1/3页
- 基于CakePHP实现的简单博客系统实例
- 基于jsp+servlet实现的简单博客系统实例(附源码)
- csdn 博客的css样式 v3
- 如何使用Gitblog和Markdown建自己的博客
- 利用JS生成博文目录及CSS定制博客
- Flask入门教程实例:搭建一个静态博客
- 让写博客成为一种习惯
- 使用微信快捷登录Wordpress博客
- 博客之前在网易安家,现在迁移到了自己开发的blog http://blog.tongbor.com
- OpenAPI 之 开源软件信息预览 ProjectTips
- 自己对博客的计划
- 做一份30字的简历
- 从主流到边缘,博客为什么不行了?
- 里程碑:博客文章阅读数突破1000万
- 博客恢复访问通知!