【线段树 细节题】bzoj1067: [SCOI2007]降雨量
主要还是细节分析;线段树作为工具
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
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
true
false
maybe
false
HINT
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9
题目分析
题意很简单,但是一道需要细细思考的细节题。
具体的思路,挂一个很详细的博客好了题解 P2471 【[SCOI2007]降雨量】。
至于具体实现我用了离散化,然后用线段树查询(x,y)区间内的最值。
1 #include<bits/stdc++.h> 2 const int maxn = 50035; 3 4 struct QRs 5 { 6 int x,y; 7 }qr[10035]; 8 struct node 9 { 10 int x,val; 11 }a[maxn]; 12 int n,m; 13 int tot[100035],t[100035],cnt; 14 int val[100035],f[400035]; 15 16 int read() 17 { 18 char ch = getchar(); 19 int num = 0; 20 bool fl = 0; 21 for (; !isdigit(ch); ch = getchar()) 22 if (ch=='-') fl = 1; 23 for (; isdigit(ch); ch = getchar()) 24 num = (num<<1)+(num<<3)+ch-48; 25 if (fl) num = -num; 26 return num; 27 } 28 void pushup(int x) 29 { 30 f[x] = std::max(f[x<<1], f[x<<1|1]); 31 } 32 void build(int rt, int l, int r) 33 { 34 if (l==r){ 35 f[rt] = val[l]; 36 return; 37 } 38 int mid = (l+r)>>1; 39 build(rt<<1, l, mid), build(rt<<1|1, mid+1, r); 40 pushup(rt); 41 } 42 int query(int rt, int L, int R, int l, int r) 43 { 44 if (L > R) return 0; 45 if (L <= l&&r <= R) return f[rt]; 46 int mid = (l+r)>>1, ret = 0; 47 if (L <= mid) ret = query(rt<<1, L, R, l, mid); 48 if (R > mid) 49 ret = std::max(ret, query(rt<<1|1, L, R, mid+1, r)); 50 return ret; 51 } 52 int main() 53 { 54 n = read(); 55 for (int i=1; i<=n; i++) 56 t[++cnt] = a[i].x = read(), a[i].val = read(); 57 m = read(); 58 for (int i=1; i<=m; i++) 59 t[++cnt] = qr[i].x = read(), t[++cnt] = qr[i].y = read(), t[++cnt] = qr[i].y-1, t[++cnt] = qr[i].x+1; 60 std::sort(t+1, t+cnt+1); 61 cnt = std::unique(t+1, t+cnt+1)-t-1; 62 int pre = 0; 63 for (int i=1; i<=n; i++) 64 { 65 int tt = std::lower_bound(t+1, t+cnt+1, a[i].x)-t; 66 val[tt] = a[i].val, tot[tt] = tot[pre]+1, pre = tt; 67 } 68 build(1, 1, cnt); 69 for (int i=1; i<=m; i++) 70 { 71 int x = std::lower_bound(t+1, t+cnt+1, qr[i].x)-t; 72 int y = std::lower_bound(t+1, t+cnt+1, qr[i].y)-t; 73 int dex = std::lower_bound(t+1, t+cnt+1, qr[i].x+1)-t; 74 int dey = std::lower_bound(t+1, t+cnt+1, qr[i].y-1)-t; 75 if (val[x]&&val[y]){ 76 if (val[x] < val[y]) puts("false"); 77 else{ 78 bool exCheck = query(1, dex, dey, 1, cnt)<val[y]; 79 if (!exCheck) puts("false"); 80 else{ 81 exCheck = exCheck&&((tot[y]-tot[x])==(qr[i].y-qr[i].x)); 82 if (!exCheck) puts("maybe"); 83 else puts("true"); 84 } 85 } 86 continue; 87 } 88 if ((!val[x])&&(!val[y])) puts("maybe"); 89 else{ 90 int secMx = query(1, dex, dey, 1, cnt); 91 if (!secMx){ 92 puts("maybe"); 93 continue; 94 } 95 if (val[x]){ 96 if (secMx >= val[x]) puts("false"); 97 else puts("maybe"); //注意这里是maybe而不是true因为中间值未知 98 } 99 if (val[y]){ 100 if (secMx >= val[y]) puts("false"); 101 else puts("maybe"); 102 } 103 } 104 } 105 return 0; 106 }
END