1926: [Sdoi2010]粟粟的书架

1926: [Sdoi2010]粟粟的书架

https://www.lydsy.com/JudgeOnline/problem.php?id=1926

 

分析:

  二分 前缀和 主席树。

  分成两问做,第一问预处理一个前缀和val[i][j][k],矩阵左上角(1,1),右下角(i,j),大于等于k的和,同样记录有多少个数num。二分最小的数。

  第二问,建立主席树,同样二分一个最小值k,然后求出大于等于k的和。判断。

  注意判断以下边界,大于等于k的可能全选上。

 

代码: 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 using namespace std;
  6 
  7 inline int read() {
  8     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
  9     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 10 }
 11  
 12 int n,m,T;
 13  
 14 namespace work1 {
 15     const int N = 205;
 16     int val[N][N][1002], num[N][N][1002], p[N][N], Mx;
 17      
 18     int getval(int a1,int b1,int a2,int b2,int k) {
 19         return val[a2][b2][k] - val[a1-1][b2][k] - val[a2][b1-1][k] + val[a1-1][b1-1][k];
 20     }
 21     int getnum(int a1,int b1,int a2,int b2,int k) {
 22         return num[a2][b2][k] - num[a1-1][b2][k] - num[a2][b1-1][k] + num[a1-1][b1-1][k];
 23     }
 24     void solve() {
 25         for (int i=1; i<=n; ++i) 
 26             for (int j=1; j<=m; ++j) 
 27                 p[i][j] = read(), Mx = max(Mx, p[i][j]);
 28         for (int k=0; k<=Mx; ++k) 
 29             for (int i=1; i<=n; ++i) 
 30                 for (int j=1; j<=m; ++j) {
 31                     val[i][j][k] += val[i-1][j][k] + val[i][j-1][k] - val[i-1][j-1][k] + (p[i][j]>=k ? p[i][j] : 0);
 32                     num[i][j][k] += num[i-1][j][k] + num[i][j-1][k] - num[i-1][j-1][k] + (p[i][j]>=k ? 1 : 0);
 33                 }
 34         while (T--) {
 35             int a1 = read(), b1 = read(), a2 = read(), b2 = read(), h = read();
 36             if (getval(a1, b1, a2, b2, 0) < h) {
 37                 puts("Poor QLW"); continue ;
 38             }
 39             int L = 0, R = Mx, ans = -1;
 40             while (L <= R) {
 41                 int mid = (L + R) >> 1;
 42                 if (getval(a1, b1, a2, b2, mid) >= h) ans = mid, L = mid + 1;
 43                 else R = mid - 1;
 44             }
 45             if (ans == -1) {
 46                 puts("Poor QLW"); continue ;
 47             }
 48             printf("%d\n",getnum(a1, b1, a2, b2, ans) - (getval(a1, b1, a2, b2, ans) - h) / ans);
 49             // 大于等于ans的并不一定取完。一共需要大于等于h,所以减去使得大于h后的最多的数,就是ans 
 50         }
 51     }
 52 }
 53 namespace work2{
 54     const int N = 500005;
 55     int ls[N*20], rs[N*20], sum[N*20], siz[N*20], Root[N], CntNode;
 56      
 57     void update(int l,int r,int &rt,int last,int p) { // 权值线段树,p既是坐标也是权值 
 58         rt = ++CntNode;
 59         sum[rt] = sum[last] + p;
 60         siz[rt] = siz[last] + 1;
 61         int mid = (l + r) >> 1;
 62         if (l == r) return ;
 63         if (p <= mid) {
 64             rs[rt] = rs[last];
 65             update(l, mid, ls[rt], ls[last], p);
 66         }
 67         else {
 68             ls[rt] = ls[last];
 69             update(mid+1, r, rs[rt], rs[last], p);
 70         }
 71     }
 72     int query(int l,int r,int Head,int Tail,int x) {
 73         if (l == r) {
 74             return ceil((double)x/l); // 向上取整,保证大于等于x 
 75             return x / l;
 76         }
 77         int mid = (l + r) >> 1, t = sum[rs[Tail]] - sum[rs[Head]];
 78         if (x > t) return siz[rs[Tail]] - siz[rs[Head]] + query(l, mid, ls[Head], ls[Tail], x-t);
 79         return query(mid+1, r, rs[Head], rs[Tail], x);
 80     }
 81      
 82     void solve() {
 83         for (int i=1; i<=m; ++i) {
 84             int x = read();
 85             update(1, 1000, Root[i], Root[i-1], x);
 86         }
 87         while (T--) {
 88             int a1 = read(), b1 = read(), a2 = read(), b2 = read(), h = read();
 89             if (sum[Root[b2]] - sum[Root[b1-1]] < h) {
 90                 puts("Poor QLW"); continue ;
 91             }
 92             printf("%d\n",query(1, 1000, Root[b1-1], Root[b2], h));
 93         }
 94     }
 95 }
 96 int main() {
 97     n = read(), m = read(), T = read();
 98     if (n != 1) work1::solve();
 99     else work2::solve(); 
100     return 0;
101 }

 

posted @ 2018-07-24 14:13  MJT12044  阅读(225)  评论(0)    收藏  举报