BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树
题目描述
幸福幼儿园 B29 班的粟粟是一个聪明机灵、乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co
rmen 的文章。粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都摆有一本书,上数第i 行、左数第j 列
摆放的书有Pi,j页厚。粟粟每天除了读书之外,还有一件必不可少的工作就是摘苹果,她每天必须摘取一个指定的
苹果。粟粟家果树上的苹果有的高、有的低,但无论如何凭粟粟自己的个头都难以摘到。不过她发现, 如果在脚
下放上几本书,就可以够着苹果;她同时注意到,对于第 i 天指定的那个苹果,只要她脚下放置书的总页数之和
不低于Hi,就一定能够摘到。由于书架内的书过多,父母担心粟粟一天内就把所有书看完而耽误了上幼儿园,于是
每天只允许粟粟在一个特定区域内拿书。这个区域是一个矩形,第 i 天给定区域的左上角是上数第 x1i行的左数
第 y1i本书,右下角是上数第 x2i行的左数第y2i本书。换句话说,粟粟在这一天,只能在这﹙x2i-x1i+1﹚×﹙
y2i-y1i+1﹚本书中挑选若干本垫在脚下,摘取苹果。粟粟每次取书时都能及时放回原位,并且她的书架不会再
撤下书目或换上新书,摘苹果的任务会一直持续 M天。给出每本书籍的页数和每天的区域限制及采摘要求,请你告
诉粟粟,她每天至少拿取多少本书,就可以摘到当天指定的苹果。
输入
第一行是三个正整数R,C,M。
接下来是一个R行C列的矩阵,从上到下、从左向右依次给出了每本书的页数Pi,j。
接下来M行,第i行给出正整数x1i,y1i,x2i,y2i,Hi,表示第i天的指定区域是﹙x1i,y1i﹚与﹙x2i,y2i﹚间
的矩形,总页数之和要求不低于Hi。
保证1≤x1i≤x2i≤R,1≤y1i≤y2i≤C。
输出
有M行,第i 行回答粟粟在第 i 天时为摘到苹果至少需要 拿取多少本书。如果即使取走所有书都无法摘到苹果,
则在该行输出“Poor QLW” (不含引号)。
样例输入
5 5 7
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108
样例输出
6
15
2
Poor QLW
9
1
3
15
2
Poor QLW
9
1
3
提示
对于 10%的数据,满足 R, C≤10;
对于 20%的数据,满足 R, C≤40;
对于 50%的数据,满足 R, C≤200,M≤200,000;
另有 50%的数据,满足 R=1,C≤500,000,M≤20,000;
对于 100%的数据,满足 1≤Pi,j≤1,000,1≤Hi≤2,000,000,000
这道题是由两道题组成的。看数据范围可以发现前50分R*C比较小,后50分是一个数列,因此分开做。首先要知道一定先选大的点结果更优。对于前50分预处理出val[i][j][k]和num[i][j][k]分别表示(1,1)到(i,j)这个矩阵中权值大于等于k的点的权值和及权值大于等于k的点的数量,然后二分答案k,O(1)验证是否满足。对于后50分因为是一个数列,所以可以在主席树上直接二分,记录区间权值和然后查询r时刻线段树减去l-1时刻线段树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | #include<map> #include<set> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int cnt; int n,m,q; int a,b,c,d,h; int f[500010]; int s[210][210]; int l[10000010]; int r[10000010]; int v[10000010]; int root[500010]; int sum[10000010]; int val[210][210][1010]; int num[210][210][1010]; bool check( int x) { if (val[c][d][x]-val[a-1][d][x]-val[c][b-1][x]+val[a-1][b-1][x]>=h) { return true ; } return false ; } void partation() { for ( int i=1;i<=n;i++) { for ( int j=1;j<=m;j++) { scanf ( "%d" ,&s[i][j]); } } for ( int k=0;k<=1000;k++) { for ( int i=1;i<=n;i++) { for ( int j=1;j<=m;j++) { if (s[i][j]>=k) { val[i][j][k]=val[i-1][j][k]+val[i][j-1][k]-val[i-1][j-1][k]+s[i][j]; num[i][j][k]=num[i-1][j][k]+num[i][j-1][k]-num[i-1][j-1][k]+1; } else { val[i][j][k]=val[i-1][j][k]+val[i][j-1][k]-val[i-1][j-1][k]; num[i][j][k]=num[i-1][j][k]+num[i][j-1][k]-num[i-1][j-1][k]; } } } } while (q--) { scanf ( "%d%d%d%d%d" ,&a,&b,&c,&d,&h); if (val[c][d][0]-val[a-1][d][0]-val[c][b-1][0]+val[a-1][b-1][0]<h) { printf ( "Poor QLW\n" ); continue ; } int l=0; int r=1001; int mid; int ans=-1; while (l<r-1) { mid=(l+r)>>1; if (check(mid)== true ) { l=mid; ans=mid; } else { r=mid; } } if (ans==-1) { printf ( "Poor QLW\n" ); continue ; } printf ( "%d\n" ,num[c][d][ans]-num[a-1][d][ans]-num[c][b-1][ans]+num[a-1][b-1][ans]-(val[c][d][ans]-val[a-1][d][ans]-val[c][b-1][ans]+val[a-1][b-1][ans]-h)/ans); } } int updata( int pre, int L, int R, int k) { int rt=++cnt; l[rt]=l[pre]; r[rt]=r[pre]; sum[rt]=sum[pre]+1; v[rt]=v[pre]+k; int mid=(L+R)/2; if (L==R) { return rt; } if (k<=mid) { l[rt]=updata(l[pre],L,mid,k); } else { r[rt]=updata(r[pre],mid+1,R,k); } return rt; } int query( int rr, int ll, int L, int R, int h) { int x=v[r[rr]]-v[r[ll]]; if (v[rr]-v[ll]<h) { return -1e9; } if (L==R) { return (h/L)+(h%L!=0); } int mid=(L+R)/2; if (x>=h) { return query(r[rr],r[ll],mid+1,R,h); } else { return query(l[rr],l[ll],L,mid,h-x)+sum[r[rr]]-sum[r[ll]]; } } int main() { scanf ( "%d%d%d" ,&n,&m,&q); if (n>1) { partation(); } else { for ( int i=1;i<=m;i++) { scanf ( "%d" ,&f[i]); root[i]=updata(root[i-1],0,1000,f[i]); } while (q--) { scanf ( "%d%d%d%d%d" ,&a,&b,&c,&d,&h); int ans=query(root[d],root[b-1],0,1000,h); if (ans<0) { printf ( "Poor QLW\n" ); } else { printf ( "%d\n" ,ans); } } } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步