bzoj1067[SCOI2007]降雨量
题意:
“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X年。由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。要求对于一个说法判断它是对、错、有可能。(即使有降雨量未知也有可能可以推出说法错误,具体看题解)信息数≤50000,询问数≤100000
题解:
本题坑点非常多。设i年<j年,要分为很多种情况:
(1)i,j均未知输出可能;(2)i知j未知,因为j最大可以和i相等,所以如果i到j之间有大于i的需输出错,否则输出可能;(3)i未知j知,如果i到j之间有大于j的输出错否则输出可能;(4)i知j知如果i到j中已知的大于j或j的信息大于i,则输出错,如果没有大于j的且i到j所有年份已知输出可能,否则输出对。
具体实现我用的是二分查年份+线段树查最大值。我在二分查询年份位置时没有处理好边界问题导致re了好多发QAQ~
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100000 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define INF 0x3fffffff 7 using namespace std; 8 9 int x[maxn],y[maxn],mx[maxn*2],n,m,mnn; 10 inline int read(){ 11 char ch=getchar(); int f=1,x=0; 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 13 return f*x; 14 } 15 void build(int x,int l,int r){ 16 if(l==r){mx[x]=y[l]; return;} int mid=(l+r)>>1; 17 build(x<<1,l,mid); build(x<<1|1,mid+1,r); mx[x]=max(mx[x<<1],mx[x<<1|1]); 18 } 19 int query(int x,int l,int r,int ql,int qr){ 20 if(ql<=l&&r<=qr)return mx[x]; int mid=(l+r)>>1,q=0; 21 if(ql<=mid)q=max(q,query(x<<1,l,mid,ql,qr)); if(qr>mid)q=max(q,query(x<<1|1,mid+1,r,ql,qr)); 22 return q; 23 } 24 int find(int y,bool a){ 25 int l=1,r=n; 26 if(a){ 27 while(l<r){ 28 int mid=l+((r-l)>>1); if(y<=x[mid])r=mid;else l=mid+1; 29 } 30 }else{ 31 while(l<r){ 32 int mid=r-((r-l)>>1); if(y<x[mid])r=mid-1;else l=mid; 33 } 34 } 35 return l; 36 } 37 int main(){ 38 n=read(); mnn=INF; inc(i,1,n)x[i]=read(),y[i]=read(),mnn=min(mnn,x[i]); 39 build(1,1,n); m=read(); 40 inc(i,1,m){ 41 int a=read(),b=read(); int c=find(a,1),d=find(b,1); 42 if(a>=b){puts("false"); continue;} 43 if(b!=x[d]){ 44 if(a!=x[c]){puts("maybe"); continue;} if(c==n){puts("maybe"); continue;} 45 if(query(1,1,n,c+1,find(b,0))>=y[c])puts("false");else puts("maybe"); continue; 46 } 47 if(a!=x[c]){ 48 if(d==1){puts("maybe"); continue;} 49 if(a<mnn){ 50 if(query(1,1,n,1,d-1)>=y[d])puts("false");else puts("maybe"); 51 }else{ 52 if(query(1,1,n,find(a,1),d-1)>=y[d])puts("false");else puts("maybe"); 53 } 54 continue; 55 } 56 if(y[d]>y[c]||query(1,1,n,c+1,d-1)>=y[d])puts("false");else{ 57 if(d-c!=b-a)puts("maybe");else puts("true"); 58 } 59 } 60 return 0; 61 }
20160628