[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]粟粟的书架 [主席树]的更多相关文章
- bzoj 1926: [Sdoi2010]粟粟的书架 (主席树+二分)
		链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1926 题面; 1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Se ... 
- 【BZOJ1926】【SDOI2010】粟粟的书架 [主席树]
		粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MB[Submit][Status][Discuss] Description 幸福幼儿园 B29 班的粟粟是一 ... 
- BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)
		BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案) 题意 : 给你一个长为\(R\)宽为\(C\)的矩阵,第\(i\)行\(j\)列的数为\(P_{i,j}\). 有\(m\)次 ... 
- bzoj1926[Sdoi2010]粟粟的书架   二分 主席树
		1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MBSubmit: 1064 Solved: 421[Submit][Stat ... 
- [bzoj1926][Sdoi2010]粟粟的书架_二分_主席树
		粟粟的书架 bzoj-1926 Sdoi-2010 题目大意:题目链接 注释:略 想法:分成两个题 前面的我们可以二分,直接二分出来检验即可. 对于R=1的,相当一个数列,我们在上面建立主席树. 然后 ... 
- Bzoj 1926: [Sdoi2010]粟粟的书架(二分答案+乱搞+主席树)
		1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MB Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱 ... 
- BZOJ1926[Sdoi2010]粟粟的书架——二分答案+主席树
		题目描述 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位 ... 
- BZOJ1926 [Sdoi2010]粟粟的书架  【主席树 + 二分 + 前缀和】
		题目 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Co rmen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都 ... 
- BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)
		题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ... 
随机推荐
- Keepalived & LVS: 实现web的负载均衡和高可用
			目录 1. 环境介绍2. LVS DR模型中Realserver上的准备3. ha上的准备4. 配置keepalived5. 测试Realserver的切换6. failback页面测试7. keep ... 
- docker介绍 架构 安装
			Docker是什么? docker是一个开源的软件部署解决方案: docker也是轻量级的应用容器框架: docker可以打包.发布.运行任何的应用. Docker 是一个开源的应用容器引擎,基于 G ... 
- Ts环境搭建
			一.ts环境搭建 安装node.js,用dos命令npm全局安装typescripe包环境 进入vscode官网下载zip文件解压后使用code.exe 
- monkey命令行测试
			一. 什么是Monkey monkey是google提供的一个用于稳定性与压力测试的命令行工具.monkey程序由android系统自带,位于/sdcard/system/framework/monk ... 
- 详解Net Core Web Api项目与在NginX下发布
			前言 本文将介绍Net Core的一些基础知识和如何NginX下发布Net Core的WebApi项目. 测试环境 操作系统:windows 10 开发工具:visual studio 2019 框架 ... 
- js垃圾回收与内存泄漏
			js垃圾回收机制 概念: javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中的使用的内存.而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况 ... 
- ID生成器之——别人家的方案and自家的方案
			“叮咚,叮咚……”,微信提示音一声接一声,声音是那么的频繁,有妖气,待俺去看一看. 这天刚吃完午饭,打开微信,发现我们的技术讨论组里有 100 多条未读消息,心想,是不是系统出问题了?怎么消息那么频繁 ... 
- 在视觉可视化中如何使用ScaleBreaks-比例中断
			从lightningChart V8开始,这项图表控件产品开始支持X轴的Scale break功能. 这个功能的主要作用是排除选定的X轴范围,例如互动交易时间/日期或者机器停产时间等.如果有一部分的数 ... 
- MySQL基础(1) | 数据类型
			MySQL基础(1) | 数据类型 数值类型 TINYINT #小整数值,1 字节,有符号(-128,127),无符号(0,255) SMALLINT #大整数值,2 字节 MEDIUMINT #大整 ... 
- 【redis】基于redis实现分布式并发锁
			基于redis实现分布式并发锁(注解实现) 说明 前提, 应用服务是分布式或多服务, 而这些"多"有共同的"redis"; (2017-12-04) 笑哭, 写 ... 
