您的位置:首页 > 其它

BZOJ_P1067&Codevs_P2439 [SCOI2007]降雨量(线段树)

2015-12-18 21:22 323 查看
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
,w
;   //年份与降雨量

//函数声明
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: