[SDOI2010]粟粟的书架 (整体二分)

版权声明:转载请注明 https://blog.csdn.net/qq_33831360/article/details/88662267

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


贪心选最大的,排序后从大到小加书,可以整体二分,加前一半,看是否满足h,满足分到前面,否则算上影响,分到后面.(两类数据分别用树状数组和二维树状数组维护)


    Problem: 1926
    User: wine
    Language: C++
    Result: Accepted
    Time:16244 ms
    Memory:24076 kb
****************************************************************/
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
void read(int &x) {
    char c;bool flag = 0;
    while((c=getchar())<'0'||c>'9') flag |= (c=='-');
    x=c-'0';while((c=getchar())>='0'&&c<='9') x=x*10+c-'0';
    if(flag) x = -x;
}
 
#define MAXN 510000
#define MAXM 201000
#define lb(x) (x&-x)
int r,c,m,tot;
 
struct E{int x,y,v;}a[MAXN];
bool cmp(const E &a,const E &b) {return a.v>b.v;}
 
struct Que {
    int x1,y1,x2,y2,hi,id,ans;
    bool p;
    void init(int x) {
       read(x1); read(y1); read(x2); read(y2); read(hi); id = x; ans = 0; 
    }
    bool inside (E a) {
       return a.x>=x1 && a.x<=x2 && a.y>=y1 && a.y<=y2;
    }
}q[MAXM],t[MAXM];
bool cmp_id(const Que &a,const Que &b) {return a.id < b.id;}
  
namespace RisNotOne {
   #define N 203
   int S[N][N],SS[N][N];
    
   void Add(int x,int y,int v) {
     for (int i = x; i <= r; i+=lb(i))
      for (int j = y; j <= c; j+=lb(j))
       S[i][j] += v;
   }
  
   int Sum(int x,int y) {
     int tmp = 0;
     for (int i = x; i >= 1; i-=lb(i))
      for (int j = y; j >= 1; j-=lb(j))
       tmp += S[i][j];
     return tmp;
   }
    
   void _Add(int x,int y,int v) {
     for (int i = x; i <= r; i+=lb(i))
      for (int j = y; j <= c; j+=lb(j))
       SS[i][j] += v;
   }
  
   int _Sum(int x,int y) {
     int tmp = 0;
     for (int i = x; i >= 1; i-=lb(i))
      for (int j = y; j >= 1; j-=lb(j))
       tmp += SS[i][j];
     return tmp;
   }
    
   int Sum(Que a) {
     return Sum(a.x2,a.y2)-Sum(a.x2,a.y1-1)-Sum(a.x1-1,a.y2)+Sum(a.x1-1,a.y1-1);
   }
    
   int _Sum(Que a) {
     return _Sum(a.x2,a.y2)-_Sum(a.x2,a.y1-1)-_Sum(a.x1-1,a.y2)+_Sum(a.x1-1,a.y1-1);
   }
    
   void slove(int l,int r,int L,int R) {
       if(l > r) return;
       if(L == R) {
          for (int i = l; i <= r; i++)
             if(q[i].hi > 0 && q[i].inside(a[L])) 
               q[i].hi -= a[L].v,q[i].ans++;
          return; 
       }
        
       int M = (L+R)>>1,tt = l;
       for (int i = L; i <= M; i++) {
         Add(a[i].x,a[i].y,a[i].v);
         _Add(a[i].x,a[i].y,1);
       }
 
       for (int i = l; i <= r; i++) 
        if(q[i].hi > 0) {
           int tmp = Sum(q[i]);
           if(tmp <= q[i].hi) {
              q[i].hi -= tmp;
              q[i].ans += _Sum(q[i]);
              q[i].p = 0; 
           } else q[i].p = 1,tt++;
        } else q[i].p = 1,tt++;
         
       for (int i = L; i <= M; i++) {
         Add(a[i].x,a[i].y,-a[i].v);
         _Add(a[i].x,a[i].y,-1);
       }
       int s = l,e = tt;
       for (int i = l; i <= r; i++)
        t[q[i].p?s++:e++] = q[i];
       for (int i = l; i <= r; i++) q[i] = t[i];
       slove(l,tt-1,L,M); slove(tt,r,M+1,R);
   }
    
   void work() {
      for (int i = 1; i <= r; i++)
        for (int j = 1; j <= c; j++) {
          read(a[++tot].v);
          a[tot].x=i; a[tot].y=j; 
        }
      for (int i = 1; i <= m; i++) q[i].init(i);
      sort(a+1,a+tot+1,cmp);
      slove(1,m,1,tot);
      sort(q+1,q+m+1,cmp_id);
      for (int i = 1; i <= m; i++)
       if(q[i].hi <= 0) printf("%d\n",q[i].ans);
       else printf("Poor QLW\n");
   }
   #undef N
}
 
namespace RisOne {
   #define N 501000
   int S[N],SS[N];
    
   void Add(int y,int v) {
      for (int j = y; j <= c; j+=lb(j)) S[j] += v;
   }
  
   int Sum(int y) {
     int tmp = 0;
     for (int j = y; j >= 1; j-=lb(j)) tmp += S[j];
     return tmp;
   }
    
   void _Add(int y,int v) {
      for (int j = y; j <= c; j+=lb(j)) SS[j] += v;
   }
  
   int _Sum(int y) {
     int tmp = 0;
     for (int j = y; j >= 1; j-=lb(j)) tmp += SS[j];
     return tmp;
   }
    
   int Sum(Que a) {return Sum(a.y2)-Sum(a.y1-1);}
    
   int _Sum(Que a) {return _Sum(a.y2)-_Sum(a.y1-1);}
    
   void slove(int l,int r,int L,int R) {
       if(l > r) return;
       if(L == R) {
          for (int i = l; i <= r; i++)
             if(q[i].hi > 0 && q[i].inside(a[L])) 
               q[i].hi -= a[L].v,q[i].ans++;
          return; 
       }
        
       int M = (L+R)>>1,tt = l;
       for (int i = L; i <= M; i++) {
         Add(a[i].y,a[i].v);
         _Add(a[i].y,1);
       }
 
       for (int i = l; i <= r; i++) 
        if(q[i].hi > 0) {
           int tmp = Sum(q[i]);
           if(tmp <= q[i].hi) {
              q[i].hi -= tmp;
              q[i].ans += _Sum(q[i]);
              q[i].p = 0; 
           } else q[i].p = 1,tt++;
        } else q[i].p = 1,tt++;
         
       for (int i = L; i <= M; i++) {
         Add(a[i].y,-a[i].v);
         _Add(a[i].y,-1);
       }
       int s = l,e = tt;
       for (int i = l; i <= r; i++)
        t[q[i].p?s++:e++] = q[i];
       for (int i = l; i <= r; i++) q[i] = t[i];
       slove(l,tt-1,L,M); slove(tt,r,M+1,R);
   }
    
   void work() {
      for(int i = 1; i <= c; i++) {
          read(a[++tot].v);
          a[tot].x=1; a[tot].y=i; 
      }
      for (int i = 1; i <= m; i++) q[i].init(i);
      sort(a+1,a+tot+1,cmp);
      slove(1,m,1,tot);
      sort(q+1,q+m+1,cmp_id);
      for (int i = 1; i <= m; i++)
       if(q[i].hi <= 0) printf("%d\n",q[i].ans);
       else printf("Poor QLW\n");
   }
   #undef N
}
 
int main() {
    read(r); read(c); read(m);
    r != 1 ? RisNotOne::work():RisOne::work();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33831360/article/details/88662267