题目

洛谷题目链接

题解

题目的数据范围非常奇怪,一半是200∗200200∗200200*200的矩阵,另一半是1∗500001∗500001*50000的矩阵,显然是一道二合一的题目,但是不一样的地方也就在与数据结构的选择不一样,而我们解这道题使用的算法是一样的,即都是二分法。

这道题所需要的数据结构应该能提供如下的功能:在O(1)O(1)O(1)或O(logn)O(logn)O(logn)的时间复杂度内查询矩阵某区间内厚度大于xxx的书本数,以及厚度大于x" role="presentation" style="position: relative;">xxx的书的页数总和。

根据上述数据结构的功能,我们可以设计一个二分算法。

即我们二分我们选取的书的最小厚度midmidmid。checkcheckcheck时候就checkcheckcheck一下矩阵内厚度≥mid≥mid≥mid的所有书的厚度之和是否能达到要求。
这样的话,二分完之后,所有厚度大于lll的书的个数就是我们的答案!
错!因为有可能厚度等于l" role="presentation" style="position: relative;">lll的书被多余使用了,因此,我们还要去掉一部分厚度为lll的书,使得总厚度仍然满足要求,但是答案变小。

算法我们已经涉及完了。
现在我们想一下怎么样设计数据结构:
当矩阵大小为200∗200" role="presentation" style="position: relative;">200∗200200∗200200*200的时候,我们定义val[i][j][k]val[i][j][k]val[i][j][k]表示矩阵区间[1,i][1,j][1,i][1,j][1,i][1,j]部分,厚度≥k≥k≥k的书的总厚度,类似的定意num[i][j][k]num[i][j][k]num[i][j][k]表示个数。
这样只需要dpdpdp一下就ok了。

当矩阵大小为1∗5000001∗5000001*500000的时候,涉及到区间操作,我们可以使用两棵主席树,一颗维护和,另一颗维护个数。

代码

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define pr(x) cout<<#x<<":"<<x<<endl
using namespace std;
const int maxn = 500007;
struct segtree{int root[maxn*20];int val[maxn*20];int lson[maxn*20];int rson[maxn*20];int id = 0;void init(){memset(root,0,sizeof(root));memset(val,0,sizeof(val));memset(lson,0,sizeof(lson));memset(rson,0,sizeof(rson));id = 0;}int ins(int &rt,int l,int r,int pos,int v){int nrt = ++id;lson[nrt] = lson[rt];rson[nrt] = rson[rt];val[nrt] = val[rt] + v;rt = nrt;if(l == r) return 0;int mid = (l+r)/2;if(pos <= mid) ins(lson[rt],l,mid,pos,v);else ins(rson[rt],mid+1,r,pos,v);}int query(int rt,int l,int r,int ul,int ur){if(!rt || ul > r || ur < l) return 0;if(ul <= l && r <= ur) return val[rt];int mid = (l+r)/2;int r1 = query(lson[rt],l,mid,ul,ur);int r2 = query(rson[rt],mid+1,r,ul,ur);return r1+r2;}
}*seg,*segcnt;
int R,C,M;
int ck1(int mid,int y1,int y2){int sm = seg->query(seg->root[y2],1,1000,mid,1000);sm -= seg->query(seg->root[y1-1],1,1000,mid,1000);return sm;
}
void solve1(){seg = new segtree;segcnt = new segtree;seg->init();segcnt->init();for(int i = 1;i <= C;++i){int v;scanf("%d",&v);seg->root[i] = seg->root[i-1];segcnt->root[i] = segcnt->root[i-1];seg->ins(seg->root[i],1,1000,v,v);segcnt->ins(segcnt->root[i],1,1000,v,1);}for(int i = 1;i <= M;++i){int x1,y1,x2,y2,h;scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&h);int l = 1,r = 1000;while(l < r){int mid = (l+r+1) / 2;if(ck1(mid,y1,y2) >= h) l = mid;else r = mid-1;}if(ck1(l,y1,y2) < h) puts("Poor QLW");else {int ans = segcnt->query(segcnt->root[y2],1,1000,l,1000);ans -= segcnt->query(segcnt->root[y1-1],1,1000,l,1000);int delta = ck1(l,y1,y2) - h;ans -= delta / l;printf("%d\n",ans);}}
}
int (*val)[201][1001],(*vc)[201][1001];
int ck2(int va[201][201][1001],int mid,int x1,int y1,int x2,int y2){int ans = va[x2][y2][mid] + va[x1-1][y1-1][mid]- va[x2][y1-1][mid] - va[x1-1][y2][mid];return ans;
}
void solve2(){val = new int[201][201][1001];vc = new int[201][201][1001];memset(val,0,sizeof(val));memset(vc,0,sizeof(vc));for(int i = 1;i <= R;++i) for(int j = 1;j <= C;++j){int tmp;scanf("%d",&tmp);for(int k = 1;k <= 1000;++k){val[i][j][k] = val[i][j-1][k] + val[i-1][j][k]- val[i-1][j-1][k];vc[i][j][k] = vc[i][j-1][k] + vc[i-1][j][k] - vc[i-1][j-1][k];if(tmp >= k) val[i][j][k] += tmp,vc[i][j][k] ++;   }}for(int i = 1;i <= M;++i){int x1,y1,x2,y2,h;scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&h);int l = 1,r = 1000;while(l < r){int mid = (l+r+1) / 2;if(ck2(val,mid,x1,y1,x2,y2) >= h) l = mid;else r = mid-1;}if(ck2(val,l,x1,y1,x2,y2) < h) puts("Poor QLW");else {int ans = ck2(vc,l,x1,y1,x2,y2);int delta = (ck2(val,l,x1,y1,x2,y2)-h)/l;ans -= delta;printf("%d\n",ans);}}
}int main()
{cin>>R>>C>>M;if(R == 1) solve1();else solve2();return 0;
}

P2468 [SDOI2010]粟粟的书架 动态规划,主席树,二分答案相关推荐

  1. BZOJ5343[Ctsc2018]混合果汁——主席树+二分答案

    题目链接: CTSC2018混合果汁 显然如果美味度高的合法那么美味度低的一定合法,因为美味度低的可选方案包含美味度高的可选方案. 那么我们二分一个美味度作为答案然后考虑如何验证? 选择时显然要贪心的 ...

  2. 粟粟的书架(主席树+二维前缀和)

    粟粟的书架 一下子做了两个题? 题意:一个问题求区间前K大的和,另一个问题求矩形内前K大的和. 思路: 前一个问题直接上主席树+二分搞定 后一个问题由于数据范围比较小,用 c n t [ i ] [ ...

  3. HDU4417 Super Mario(离线树状数组或者主席树+二分)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. P2468 [SDOI2010]粟粟的书架 主席树 + 二分 + 二维前缀和

    传送门 文章目录 题意: 题意: 题意: 给你一个n∗mn*mn∗m的矩阵,每次询问一个矩形,左上角是(x1,y1)(x_1,y_1)(x1​,y1​),右上角是(x2,y2)(x_2,y_2)(x2 ...

  5. P2468-[SDOI2010]粟粟的书架【主席树,二维前缀和】

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P2468 题目大意 对于每一个询问,求一个区域内最少取多少个数使它们的 ...

  6. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  7. Just h-index(主席树+二分)

    链接:https://ac.nowcoder.com/acm/contest/1107/C 来源:牛客网 找一段区间内,大于等于这个数的个数大于等于这个数本身,问符合条件的最大值是多少. 思路:把数据 ...

  8. K-th Closest Distance HDU - 6621(第k小绝对值+主席树+二分)

    You have an array: a1, a2, , an and you must answer for some queries. For each query, you are given ...

  9. Cutting Bamboos(牛客多校第九场H主席树+二分+思维)

    链接:https://ac.nowcoder.com/acm/contest/889/H 来源:牛客网 There are n bamboos arranged in a line. The i-th ...

最新文章

  1. vscode remote ssh 远程开发免密登陆方法
  2. Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)(转)
  3. Java EE WEB工程师培训-JDBC+Servlet+JSP整合开发之14.Servlet请求头信息
  4. hibernate07--关联映射
  5. android微信动画制作,动画制作轻量级SDK:PAG六大优势助力开发
  6. linux同时安装python2和python3_linux-Centos7安装python3并与python2共存
  7. Oracle的latch机制源代码解析——借postgresql猜测Oracle的latch
  8. python运维都做些什么_python运维工程师主要干什么
  9. 为什么在使用超级终端配置交换机时显示乱码或无显示?
  10. 对话框ModifyStyle(0, WS_MINIMIZEBOX)最小化按钮无效的解决方法
  11. MeteoInfo-Micaps绘制色斑图
  12. 如何将文字转换为二维码 python_用python将二维码转换成字符直接输出控制台
  13. 烤仔的朋友们 | 从薯片到卫生纸,进入NFT市场的10大传统品牌大盘点
  14. PDF怎么快速转换成Excel表格文件?两个方法帮你实现
  15. 使用wvdial启动ppp协议拨号上网
  16. JS解析json数据(json字符串和数组之间相互转换)
  17. strstr(str1,str2)函数使用时注意事项
  18. Https/Tcp抓包工具Charles、fiddler,ping (网络诊断工具),Android平台HTTPS抓包解决方案及问题分析HttpCanary
  19. Kotlin 协程 (1/7篇) - 协程概念 Coroutine
  20. Q_OBJECT的作用

热门文章

  1. spss22.0统计分析从入门到精通_数据分析最全资料:SPSS/MATLAB/SQL/SAS/EXCEL经典教材+视频教程,快速入门!...
  2. 三菱plc选型手册_模拟量是什么?PLC和模拟量是如何转换的?
  3. 算法设计与分析——算法思想总结
  4. 用计算机组成原理+唐朔飞的,计算机组成原理 唐朔飞 习题解答
  5. 类加载机制(整个过程详解)
  6. [C++11]推荐使用auto的场景
  7. 数据结构与算法--有序数组中找出和为s的两个数字
  8. Ubuntu上安装使用Docker
  9. mysql 5.74安装教程_MySQL安装、基本账户安全(5.0以后版本)
  10. 算法----最大承载量下的最大价值问题