Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 2915 Solved: 745
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
6
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008
Sample Output
false
true
false
maybe
false
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9
Source
POJ 2637 WorstWeather Ever
我去简直了,恶心到爆,让我冷静一下
#include<cstdio>
#include<map>
#include<iostream>
using namespace std;
#define N 150000 //数据范围
//变量声明
struct node{
int ma,l,r; //最大值,左右
bool un; //是否存在未知
}s[N*2]; //节点
map<int,int> cl; //年份对应降雨量
int n,t,m; //数据数目,总数,询问数目
int y[N],w[N]; //年份与降雨量
//函数声明
void build(int o,int l,int r);//建立线段树
bool find(int x);//年份出现
void init(node& x);//初始化节点
void by(node a,node b,node& p);//节点合并
node query(int o,int l,int r);//查询函数
int ef(int x,bool ord);//二分查找
int in();//读入优化
//主函数
int main(){
n=in();int tt;
for(int i=1;i<=n;i++){
y[i]=in(),tt=in();
if(i!=1&&y[i]-1!=y[i-1]) w[++t]=-1;
w[++t]=tt;
cl[y[i]]=t;
}
build(1,1,t);m=in();
int ll,rr;bool xx,yy;node ans; //左右端点 是否出现
while(m--){
ll=in(),rr=in();
xx=find(ll),yy=find(rr);
if((!xx)&&(!yy)){printf("maybe\n");continue;}//都未知,就是maybe
if(xx&&yy){ //均已知
if(ll==rr) {printf("maybe\n");continue;}
ll=cl[ll],rr=cl[rr];
if(w[ll]<w[rr]){printf("false\n");continue;}
ans=query(1,ll+1,rr-1);
if(ans.ma>=w[rr]) {printf("false\n");continue;}
if(ans.un) {printf("maybe\n");continue;}
{printf("true\n");continue;}
}
else if(xx&&(!yy)){ //后未知
rr=ef(rr,true);
if(ll==rr) {printf("maybe\n");continue;}
ll=cl[ll],rr=cl[rr];
ans=query(1,ll+1,rr);
if(w[ll]<=ans.ma) {printf("false\n");continue;}
{printf("maybe\n");continue;}
}
else{ //前未知
ll=ef(ll,false);
if(ll==rr) {printf("maybe\n");continue;}
ll=cl[ll],rr=cl[rr];
ans=query(1,ll,rr-1);
if(w[rr]<=ans.ma) {printf("false\n");continue;}
{printf("maybe\n");continue;}
}
}
return 0;
}
//建立线段树
void build(int o,int l,int r){
if(l==r){
s[o].ma=w[l];s[o].l=s[o].r=l;
if(w[l]<0) s[o].un=true;
return;
}
int m=(l+r)>>1;
build(o*2,l,m);build(o*2+1,m+1,r);
s[o].ma=max(s[o*2].ma,s[o*2+1].ma);
s[o].un=(s[o*2].un||s[o*2+1].un);
s[o].l=l,s[o].r=r;
return;
}
//查找年份是否出现
bool find(int x){
return cl.find(x)!=cl.end(); //找到返回true 未找到返回false
}
//初始化节点
void init(node& x){
x.ma=0,x.un=false;return;
}
//节点合并
void by(node a,node b,node& p){
p.ma=max(a.ma,b.ma);p.un=(a.un||b.un);
return;
}
//查询函数
node query(int o,int l,int r){
if(l<=s[o].l&&r>=s[o].r) return s[o];
int m=(s[o].l+s[o].r)>>1;node p,k,res;
init(p);init(k);
if(l<=m) p=query(o*2,l,r);
if(r>m) k=query(o*2+1,l,r);
by(p,k,res);
return res;
}
//二分查找
int ef(int x,bool ord){ //ord=true,maxl;ord=false,minr;
int l=1,r=n,m;
while(l<r){
m=(l+r)>>1;
if(y[m]<x) l=m+1;
else r=m;
}
if(ord) if(y[l]>x) l--;
if(!ord) if(y[l]<x) l++;
return y[l];
}
//读入优化
int in(){
int x=0,v=1;char ch=getchar();
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') ch=getchar(),v=-1;
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*v;
}