[SDOI2010]粟粟的书架

考虑暴力怎么做 显然是提取出来 (x2-x1+1)*(y2-y1+1) 个数字拿出来 然后从大到小排序

然后就可以按次取数了…

然而接下来看数据范围

\(50\%\ r,c\leq 200\)

\(50\%\ r=1,c\leq 5*10^5\)

值域 \(\in [1,1000]\)

对于前 50% 可以用个前缀和搞定…

令 \(sum_{i,j,k}\) 为 大于 k 的前缀和

\(num_{i,j,k}\) 为 大于 k 的前缀和数量

然后愉快的二分?

另外50%主席树乱草

看准值域直接二分

前面的复杂度是 \(O(rc \log max{a_i})\)

后面的复杂度是 \(O(rc \log^2 max{a_i})\)

直接考虑当前有多少…

还有一个显而易见的性质

如果当前最优解为\(ans\) 那么肯定存在数字\(ans\) 以及 \(sum-h < cnt*ans\)

算出来除一下就可以了我也不知道为什么我脑抽写了一直减…还查询了个数…


#include <bits/stdc++.h>
// #define int long long
#define rep(a , b , c) for(register int a = b ; a <= c ; ++ a)
#define Rep(a , b , c) for(register int a = b ; a >= c ; -- a)
#define go(u) for(int i = G.head[u] , v = G.to[i] , w = e[i].dis ; i ; v = G.to[i = G.nxt[i]] , w = e[i].dis) using namespace std ;
using ll = long long ;
using pii = pair < int , int > ;
using vi = vector < int > ; inline int read() {
register int x = 0 ;
bool f = 1 ;
register char c = getchar() ;
while(c < 48 || c > 57) {
if(c == '-') f = 0 ;
c = getchar() ;
}
while(c > 47 && c < 58) {
x = (x << 1) + (x << 3) + (c & 15) ;
c = getchar() ;
}
return f ? x : -x ;
} template <class T> inline void print(T x , char c = '\n') {
static char st[100] ;
int stp = 0 ;
if(! x) {
putchar('0') ;
}
if(x < 0) {
x = -x ;
putchar('-') ;
}
while(x) {
st[++ stp] = x % 10 ^ 48 ;
x /= 10 ;
}
while(stp) {
putchar(st[stp --]) ;
}
putchar(c) ;
} template <class T> void cmax(T & x , T y) {
x < y ? x = y : 0 ;
}
template <class T> void cmin(T & x , T y) {
x > y ? x = y : 0 ;
} const int _N = 1e6 + 10 ;
struct Group {
int head[_N] , nxt[_N << 1] , to[_N] , dis[_N] , cnt = 1 ;
Group () {
memset(head , 0 , sizeof(head)) ;
}
void add(int u , int v , int w = 1) {
nxt[++ cnt] = head[u] ;
to[cnt] = v ;
dis[cnt] = w ;
head[u] = cnt ;
}
} ; const int N = 1e5 + 10 ;
typedef int arr[N] ;
int r , c , m ;
const int N1 = 233 ;
const int N2 = 5e5 + 10 ;
int len = 0 ;
int a[N1][N1] ;
//struct Small_Tree {
// int rt[N1] , cnt = 0 , ls[N1 << 5] , rs[N1 << 5] , sum[N1 << 5] , sz[N1 << 5] ;
// void upd(int pre , int & p , int l , int r , int val) {
// ls[p = ++ cnt] = ls[pre] , rs[p] = rs[pre] ;
// sum[p] = sum[pre] + val , sz[p] = sz[pre] + 1 ;
// if(l == r) return ;
// int mid = l + r >> 1 ;
// val <= mid ? upd(ls[pre] , ls[p] , l , mid , val) : upd(rs[pre] , rs[p] , mid + 1 , r , val) ;
// }
// int query(int a , int b , int pre , int p , int l , int r) {
// if(a <= l && r <= b) return sum[p] - sum[pre] ;
// int mid = l + r >> 1 , ans = 0 ;
// if(a <= mid) ans += query(a , b , ls[pre] , ls[p] , l , mid) ;
// if(b > mid) ans += query(a , b , rs[pre] , rs[p] , mid + 1 , r) ;
// return ans ;
// }
// int query_sz(int a , int b , int pre , int p , int l , int r) {
// if(a <= l && r <= b) return sz[p] - sz[pre] ;
// int mid = l + r >> 1 ;
// int ans = 0 ;
// if(a <= mid) ans += query_sz(a , b , ls[pre] , ls[p] , l , mid) ;
// if(b > mid) ans += query_sz(a , b , rs[pre] , rs[p] , mid + 1 , r) ;
// return ans ;
// }
//} t[233] ;
//void solve1() {
// rep(i , 1 , r) rep(j , 1 , c) a[i][j] = read() ;
// rep(i , 1 , r) rep(j , 1 , c) cmax(len , a[i][j]) ;
// rep(i , 1 , r) rep(j , 1 , c) t[i].upd(t[i].rt[j - 1] , t[i].rt[j] , 1 , len , a[i][j]) ;
// while(m --) {
// int x1 = read() , y1 = read() , x2 = read() , y2 = read() , h = read() ;
// int l = 0 , r = len + 1 ;
// int ans = -1 ;
// while(l <= r) {
// int mid = l + r >> 1 , sum = 0 ;
// rep(i , x1 , x2) sum += t[i].query(mid , len , t[i].rt[y1 - 1] , t[i].rt[y2] , 1 , len) ;
// if(sum >= h) {
// ans = mid ;
// l = mid + 1 ;
// }
// else r = mid - 1 ;
// }
// if(ans == -1) {
// puts("Poor QLW") ;
// continue ;
// }
// int tot = 0 , onlytot = 0 , sum = 0 ;
// rep(i , x1 , x2) sum += t[i].query(ans , len , t[i].rt[y1 - 1] , t[i].rt[y2] , 1 , len) ;
// rep(i , x1 , x2) tot += t[i].query_sz(ans , len , t[i].rt[y1 - 1] , t[i].rt[y2] , 1 , len) ;
// rep(i , x1 , x2) onlytot += t[i].query_sz(ans , ans , t[i].rt[y1 - 1] , t[i].rt[y2] , 1 , len) ;
// int cnt = 0 ;
// while(sum - ans >= h && cnt < onlytot) {
// sum -= ans ;
// cnt ++ ;
// }
// print(tot - cnt) ;
// }
//} int val[N1][N1][1005] ;
int num[N1][N1][1005] ;
int get_val(int a1 , int b1 , int a2 , int b2 , int k) {
return val[a2][b2][k] - val[a1 - 1][b2][k] - val[a2][b1 - 1][k] + val[a1 - 1][b1 - 1][k] ;
}
int get_num(int a1 , int b1 , int a2 , int b2 , int k) {
return num[a2][b2][k] - num[a1 - 1][b2][k] - num[a2][b1 - 1][k] + num[a1 - 1][b1 - 1][k] ;
}
void solve1() {
rep(i , 1 , r) rep(j , 1 , c) {
a[i][j] = read() ;
cmax(len , a[i][j]) ;
}
rep(k , 0 , len) {
rep(i , 1 , r) {
rep(j , 1 , c) {
val[i][j][k] = val[i - 1][j][k] + val[i][j - 1][k] - val[i - 1][j - 1][k] + (a[i][j] >= k ? a[i][j] : 0) ;
num[i][j][k] = num[i - 1][j][k] + num[i][j - 1][k] - num[i - 1][j - 1][k] + (a[i][j] >= k ? 1 : 0) ;
}
}
}
while(m --) {
int a1 = read() , b1 = read() , a2 = read() , b2 = read() , h = read() ;
if(get_val(a1 , b1 , a2 , b2 , 0) < h) {
puts("Poor QLW") ;
continue ;
}
int l = 0 , r = len + 1 , ans = -1 ;
while(l <= r) {
int mid = l + r >> 1 ;
if(get_val(a1 , b1 , a2 , b2 , mid) >= h) {
ans = mid ;
l = mid + 1 ;
}
else r = mid - 1 ;
}
if(ans == -1) {
puts("Poor QLW") ;
continue ;
}
print(get_num(a1 , b1 , a2 , b2 , ans) - ((get_val(a1 , b1 , a2 , b2 , ans) - h) / ans)) ;
}
}
struct Big_Tree {
int rt[N2] , cnt = 0 ;
int ls[N2 << 5] , rs[N2 << 5] , sum[N2 << 5] , sz[N2 << 5] ;
void upd(int pre , int & p , int l , int r , int val) {
ls[p = ++ cnt] = ls[pre] ;
rs[p] = rs[pre] ;
sum[p] = sum[pre] + val ;
sz[p] = sz[pre] + 1 ;
if(l == r) return ;
int mid = l + r >> 1 ;
val <= mid ? upd(ls[pre] , ls[p] , l , mid , val) : upd(rs[pre] , rs[p] , mid + 1 , r , val) ;
}
int query(int a , int b , int pre , int p , int l , int r) {
if(a <= l && r <= b) return sum[p] - sum[pre] ;
int mid = l + r >> 1 ;
int ans = 0 ;
if(a <= mid) ans += query(a , b , ls[pre] , ls[p] , l , mid) ;
if(b > mid) ans += query(a , b , rs[pre] , rs[p] , mid + 1 , r) ;
return ans ;
}
int query_sz(int a , int b , int pre , int p , int l , int r) {
if(a <= l && r <= b) return sz[p] - sz[pre] ;
int mid = l + r >> 1 ;
int ans = 0 ;
if(a <= mid) ans += query_sz(a , b , ls[pre] , ls[p] , l , mid) ;
if(b > mid) ans += query_sz(a , b , rs[pre] , rs[p] , mid + 1 , r) ;
return ans ;
}
} bigt ;
vi v ;
void solve2() {
v.resize(c + 1) ;
rep(i , 1 , c) v[i] = read() ;
rep(i , 1 , c) cmax(len , v[i]) ;
rep(i , 1 , c) bigt.upd(bigt.rt[i - 1] , bigt.rt[i] , 1 , len , v[i]) ;
while(m --) {
int x1 = read() , y1 = read() , x2 = read() , y2 = read() , h = read() ;
int l = 0 , r = len + 1 , ans = -1 ;
while(l <= r) {
int mid = l + r >> 1 ;
int sum = bigt.query(mid , len , bigt.rt[y1 - 1] , bigt.rt[y2] , 1 , len) ;
if(sum >= h) {
ans = mid ;
l = mid + 1 ;
}
else r = mid - 1 ;
}
if(ans == -1) {
puts("Poor QLW") ;
continue ;
}
int tot = 0 , onlytot = 0 , sum = 0 ;
sum = bigt.query(ans , len , bigt.rt[y1 - 1] , bigt.rt[y2] , 1 , len) ;
tot = bigt.query_sz(ans , len , bigt.rt[y1 - 1] , bigt.rt[y2] , 1 , len) ;
onlytot = bigt.query_sz(ans , ans , bigt.rt[y1 - 1] , bigt.rt[y2] , 1 , len) ;
int cnt = 0 ;
while(sum - ans >= h && cnt < onlytot) { sum -= ans ; cnt ++ ; }
print(tot - cnt) ;
}
}
signed main() {
r = read() ; c = read() ; m = read() ;
if(r ^ 1) solve1() ;
else solve2() ;
return 0 ;
}

[SDOI2010]粟粟的书架 [主席树]的更多相关文章

  1. bzoj 1926: [Sdoi2010]粟粟的书架 (主席树+二分)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1926 题面; 1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Se ...

  2. 【BZOJ1926】【SDOI2010】粟粟的书架 [主席树]

    粟粟的书架 Time Limit: 30 Sec  Memory Limit: 552 MB[Submit][Status][Discuss] Description 幸福幼儿园 B29 班的粟粟是一 ...

  3. BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)

    BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案) 题意 : 给你一个长为\(R\)宽为\(C\)的矩阵,第\(i\)行\(j\)列的数为\(P_{i,j}\). 有\(m\)次 ...

  4. bzoj1926[Sdoi2010]粟粟的书架 二分 主席树

    1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec  Memory Limit: 552 MBSubmit: 1064  Solved: 421[Submit][Stat ...

  5. [bzoj1926][Sdoi2010]粟粟的书架_二分_主席树

    粟粟的书架 bzoj-1926 Sdoi-2010 题目大意:题目链接 注释:略 想法:分成两个题 前面的我们可以二分,直接二分出来检验即可. 对于R=1的,相当一个数列,我们在上面建立主席树. 然后 ...

  6. Bzoj 1926: [Sdoi2010]粟粟的书架(二分答案+乱搞+主席树)

    1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MB Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱 ...

  7. BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树

    题目描述 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位 ...

  8. BZOJ1926 [Sdoi2010]粟粟的书架 【主席树 + 二分 + 前缀和】

    题目 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都 ...

  9. BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)

    题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...

随机推荐

  1. Java DTO(data transfer object)的理解

    首先明白springboot每层 model层 model层即数据库实体层,也被称为entity层,pojo层. 一般数据库一张表对应一个实体类,类属性同表字段一一对应. Model层是数据层: Ta ...

  2. 一本彻底搞懂MySQL索引优化EXPLAIN百科全书

    1.MySQL逻辑架构 日常在CURD的过程中,都避免不了跟数据库打交道,大多数业务都离不开数据库表的设计和SQL的编写,那如何让你编写的SQL语句性能更优呢? 先来整体看下MySQL逻辑架构图: M ...

  3. php oci 和 pdo_oci 安装

    安装非常复杂,必须记录 CentOS服务器上已有相关环境:apache.php5 需要安装:1.oracle客户端.2.oci8扩展.3.pdo_oci扩展. 一. 准备文件 1) oracle客户端 ...

  4. pt-query-digest 慢日志监控

    一.安装percona-toolkit,以centos为例 yum -y install https://repo.percona.com/yum/percona-release-latest.noa ...

  5. Nginx-2.初学者使用

    原文 Nginx有一个master进程和几个worker进程.master进程用来读取和评估配置文件,以及维护worker进程.worker进程用来处理实际的请求.Nginx使用事件模型和基于操作系统 ...

  6. Mysql性能优化全揭秘-庖丁解牛

    「为什么写」 一直想写数据库相关的文章,最直接的原因是数据库这块我们工作中每天都会用到,也是面试求职绕不开的话题,无论你是何种测试,优秀的数据库能力都会非常加分,最近我在总结数据库性能优化这块内容,性 ...

  7. MD5加密常用js库:crypto-js

    学习链接:https://github.com/brix/crypto-js

  8. weblogic非正常关闭,<BEA-141281>错误

    在域下 find -name *.lok , 全删除: 在域下 find -name *.DAT,全删除: 然后就可以正常启动了

  9. Mysql 保存emoji表情报错

    保存emoji表情错误 首先错误表现,抛出业务层报错之外,根源的数据库错误是: sql 错误码 1366 字符集相关错误. uncategorized SQLException; SQL state ...

  10. C#制作Wincc组件进行配方管理

    1,安装WinccV7.4并破解: 安装WinccV7.4SP1. 安装授权文件---根据提示 安装免狗驱动,根据提示 安装SImatic.net v13. 2,连接PLC, 首先在同一个局域网里面, ...