zoukankan      html  css  js  c++  java
  • bzoj 1926[Sdoi2010]粟粟的书架

    1926: [Sdoi2010]粟粟的书架

    Time Limit: 30 Sec  Memory Limit: 512 MB

    Description

    幸福幼儿园 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天。给出每本书籍的页数和每天的区域限制及采摘要求,请你告
    诉粟粟,她每天至少拿取多少本书,就可以摘到当天指定的苹果。

    Input

    第一行是三个正整数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。

    Output

    有M行,第i 行回答粟粟在第 i 天时为摘到苹果至少需要 拿取多少本书。如果即使取走所有书都无法摘到苹果,
    则在该行输出“Poor QLW” (不含引号)。

    Sample Input

    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

    Sample Output

    6
    15
    2
    Poor QLW
    9
    1
    3

    HINT

    对于 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

    看到数据就知道这题是两种分别写

    对于R = 1 的,我们在主席树上进行查询

    另一个则记录下前缀和进行二分

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define LL long long
      6 #define lc seg[x].l
      7 #define rc seg[x].r
      8 
      9 using namespace std;
     10 
     11 const int MAXN = 5e5 + 10;
     12 int R, C, M;
     13 int flag = 0;
     14 LL ans = 0;
     15 int tot = 0;
     16 int root[MAXN];
     17 int page[210][210];
     18 int sum[210][210][1100];
     19 int num[210][210][1100];
     20 
     21 inline LL read()
     22 {
     23     LL x = 0, w = 1; char ch = 0;
     24     while(ch < '0' || ch > '9') {
     25         if(ch == '-') {
     26             w = -1;
     27         }
     28         ch = getchar();
     29     }
     30     while(ch >= '0' && ch <= '9') {
     31         x = x * 10 + ch - '0';
     32         ch = getchar();
     33     }
     34     return x * w;
     35 }
     36 
     37 struct segment {
     38     int l, r;
     39     int sum;
     40     int num;
     41 } seg[MAXN * 15];
     42 
     43 void pushup(int x)
     44 {
     45     seg[x].num = seg[lc].num + seg[rc].num;
     46     seg[x].sum = seg[lc].sum + seg[rc].sum;
     47 }
     48 
     49 void add(int l, int r, int &x, int k)
     50 {
     51     seg[++tot] = seg[x];
     52     x = tot;
     53     if(l == r) {
     54         seg[x].sum += k;
     55         seg[x].num++;
     56         return;
     57     }
     58     int mid = (l + r) >> 1;
     59     if(k > mid) {
     60         add(mid + 1, r, seg[tot].r, k);
     61     } else {
     62         add(l, mid, seg[tot].l, k);
     63     }
     64     pushup(x);
     65 }
     66 
     67 void query(int l, int r, int x1, int x2, int sum)
     68 {
     69     int mid = (l + r) >> 1;
     70     if(l == r) {
     71         if(seg[x2].sum - seg[x1].sum < sum) {
     72             flag = -1;
     73         }
     74         ans += (sum - 1) / l + 1;
     75         return;
     76     }
     77     int SUM = seg[seg[x2].r].sum - seg[seg[x1].r].sum;
     78     if(SUM >= sum) {
     79         query(mid + 1, r, seg[x1].r, seg[x2].r, sum);
     80     } else {
     81         ans += seg[seg[x2].r].num - seg[seg[x1].r].num;
     82         query(l, mid, seg[x1].l, seg[x2].l, sum - SUM);
     83     }
     84 }
     85 
     86 int main()
     87 {
     88 //    cout<<sizeof(sum) / 1024 / 1024<<endl;
     89     R = read(), C = read(), M = read();
     90     if(R == 1) {
     91         for(int i = 1; i <= C; i++) {
     92             int k = read();
     93             root[i] = root[i - 1]; 
     94             add(1, 1000, root[i], k);
     95         }
     96         for(int i = 1; i <= M; i++) {
     97             ans = 0;
     98             flag = 0;
     99             int x1 = read(), y1 = read(), x2 = read(), y2 = read();
    100             int h = read();
    101             int l = 1, r = 1000;
    102             query(1, 1000, root[y1 - 1], root[y2], h);
    103             if(flag == -1) {
    104                 printf("Poor QLW
    ");
    105             } else {
    106                 printf("%lld
    ", ans);
    107             }
    108         }
    109     } else {
    110         for(int i = 1; i <= R; i++) {
    111             for(int j = 1; j <= C; j++) {
    112                 page[i][j] = read();
    113             }
    114         }
    115         for(int k = 1; k <= 1000; k++) {
    116             for(int i = 1; i <= R; i++) {
    117                 for(int j = 1; j <= C; j++) {
    118                     num[i][j][k] = num[i - 1][j][k] + num[i][j - 1][k] - num[i - 1][j - 1][k] + (page[i][j] >= k ? 1 : 0);
    119                     sum[i][j][k] = sum[i - 1][j][k] + sum[i][j - 1][k] - sum[i - 1][j - 1][k] + (page[i][j] >= k ? page[i][j] : 0);
    120                 }
    121             }
    122         }
    123         for(int i = 1; i <= M; i++) {
    124             int x1 = read(), y1 = read(), x2 = read(), y2 = read(), h = read();
    125             int l = 1, r = 1000;
    126             int ans = 0;
    127             while(l <= r) {
    128                 int mid = (l + r) >> 1;
    129                 if(sum[x2][y2][mid] - sum[x1 - 1][y2][mid] - sum[x2][y1 - 1][mid] + sum[x1 - 1][y1 - 1][mid] >= h) {
    130                     ans = mid;
    131                     l = mid + 1;
    132                 } else {
    133                     r = mid - 1;
    134                 }
    135             }
    136             if(ans == 0) {
    137                 printf("Poor QLW
    ");
    138             } else {
    139                 LL NUM = num[x2][y2][ans + 1] - num[x1 - 1][y2][ans + 1] - num[x2][y1 - 1][ans + 1] + num[x1 - 1][y1 - 1][ans + 1];
    140                 LL SUM = sum[x2][y2][ans + 1] - sum[x1 - 1][y2][ans + 1] - sum[x2][y1 - 1][ans + 1] + sum[x1 - 1][y1 - 1][ans + 1];
    141                 ans = NUM + (h - SUM - 1) / ans + 1;
    142                 printf("%lld
    ", ans);
    143             }
    144         }
    145     }
    146 
    147 }
    148 
    149 
    150 /*
    151 
    152 5 5 7
    153 14 15 9 26 53
    154 58 9 7 9 32
    155 38 46 26 43 38
    156 32 7 9 50 28
    157 8 41 9 7 17
    158 1 2 5 3 139
    159 3 1 5 5 399
    160 3 3 4 5 91
    161 4 1 4 1 33
    162 1 3 5 4 185
    163 3 3 4 3 23
    164 3 1 3 3 108
    165 
    166 */
    View Code
  • 相关阅读:
    webpack的最简单应用,只使用js与css的打包
    数据统计表插件,highcharts插件的简单应用
    C#中的特性 (Attribute) 入门 (二)
    C#中的特性 (Attribute) 入门 (一)
    SQLServer存储过程入门
    C#拖拽操作
    C#剪切板
    .Net中的IO
    Android四大组件-服务
    AlertDialog对话框
  • 原文地址:https://www.cnblogs.com/wuenze/p/9151220.html
Copyright © 2011-2022 走看看