1. 程式人生 > >bzoj 1067: [SCOI2007]降雨量

bzoj 1067: [SCOI2007]降雨量

lin spa 一道 span scoi2007 二分 getc down 年份

題目鏈接:

bzoj 1067: [SCOI2007]降雨量

題解:

很簡單的一道題,但代碼裏有許多細節需要註意,切容易出錯,調了三個小時OTZ
做一個st表維護區間最大值就
在獲得年份在序列中的pos時二分
也可以維護平衡樹查詢pos
或者用直接用線段維護最大值同時維護區間中有多少年份
其次分情況討論就好了

#include<cmath>
#include<cstdio>
#include<algorithm>
inline int read() {
    int x=0,f=1;
    char c=getchar() ;
    while(c<'0'
||c>'9') {if(c=='-')f=-1;c=getchar();} while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar(); return x*f; } const int maxn = 50007; int a[maxn],b[maxn];int f[maxn][21],n; void make_st() { for(int i=1;i<=20;++i) for(int j=1;j+(1<<i)-1
<=n;++j) f[j][i]=std::max(f[j][i-1],f[j+(1<<(i-1))][i-1]); } int query(int l,int r) { if (l>r) return-0x7fffffff; int q=log(r-l+1)/log(2); return std::max(f[l][q],f[r-(1<<q)+1][q]); } int getpos(int f) { int l=1,r=n,ret=0; while(l<=r) { int
mid=l+r>>1; if(a[mid]<=f)ret=mid,l=mid+1; else r=mid-1; } return ret; } int main() { n=read(); for(int i=1;i<=n;++i) { a[i]=read(),b[i]=read();f[i][0]=b[i]; } make_st(); int m=read() ; for(int a1,b1;m--;) { a1=read() ,b1=read(); int pa=getpos(a1),pb=getpos(b1); if(a[pa]!=a1&&a[pb]!=b1) {puts("maybe");continue;} if(a[pa]!=a1&&a[pb]==b1) { if(query(pa+1,pb-1)<b[pb])puts("maybe"); else puts("false");continue; } if(a[pa]==a1&&a[pb]!=b1) { if(query(pa+1,pb)<b[pa])puts("maybe"); else puts("false");continue; } if(pb-pa!=b1-a1) { if(query(pa+1,pb-1)>=b[pb]||b[pb]>=b[pa]) puts("false"); else puts("maybe");continue; } if(query(pa+1,pb-1)<b[pb]&&b[pa]>b[pb]) puts("true"); else puts("false"); //printf("max(pa -> pb) : %d\n",query(pa+1,pb)); } return 0; }

bzoj 1067: [SCOI2007]降雨量