「Luogu P2468 [SDOI2010]粟粟的书架」
这道题分为两个部分
Part1
前置芝士
具体做法
可以发现\(R,C\)不大,只有\(200\),于是可以先预处理出一个数组\(a[i][j][k]\),表示从\((1,1)\)~\((i,j)\)中高度为k的书出现的次数,也可以理解为一个二维前缀和,考虑贪心,所以肯定是会优先去拿高的书,于是需要再处理两个数组\(b[i][j][k]\),表示\((1,1)\)~\((i,j)\)中高度在\(k\)~\(1000\)的范围内的书的出现次数,就是在\(a\)数组的基础上加上一个后缀和,以及\(c[i][j][k]\),表示\((1,1)\)~\((i,j)\)中高度在\(k\)~\(1000\)的范围内的书的总高度,处理方法和\(b\)数组类似.这样就可以在\(O(1)\)的复杂度计算出拿取规定区域内的书中高度在\(k\)~\(1000\)的范围内的书的总高度和本数,计算方法与二维前缀和计算矩阵和类似(写这种题应该不会有人不会吧).接下来可以用一个二分,很快速得计算出需要取从多少高度开始的书,但是,这样计算出来的不是答案,这个高度的书未必就一定会全部取完,所以还需要将那些多取的书减去.
代码
long long arr[233][233][1024];
int num[233][233][1024];
long long sum[1024];
long long Get(int fx,int fy,int lx,int ly,int num)//计算从(fx,fy)~(lx,ly)中num~1000的高度的书的高度和
{
	//计算方法为一个简单的容斥,如果实在不能理解建议先做一下P3138
	return arr[lx][ly][num]-arr[fx-1][ly][num]-arr[lx][fy-1][num]+arr[fx-1][fy-1][num];
}
int GetCnt(int fx,int fy,int lx,int ly,int top)//计算从(fx,fy)~(lx,ly)中top~1000的高度的书的本书
{
	return num[lx][ly][top]-num[fx-1][ly][top]-num[lx][fy-1][top]+num[fx-1][fy-1][top];
}
void Cry()//没法摘到苹果...
{
	printf("Poor QLW\n");
}
void Solve1()//解决第一部分
{
	scanf("%d",&T);
	int high;
	REP(i,1,N)
	{
		REP(j,1,1000)//先清空这个一维的前缀
		{
			sum[j]=0;
		}
		REP(j,1,M)
		{
			scanf("%d",&high);
			sum[high]++;//在一维前缀中++
			REP(k,1,1000)//当前的每个数出现的次数为这个位置上面的每个数出现的次数+这个一维前缀中每个数出现的次数
			{
				arr[i][j][k]=arr[i-1][j][k]+sum[k];
			}
		}
	}
	REP(i,1,N)
	{
		REP(j,1,M)
		{
			DOW(k,1000,1)
			{
				num[i][j][k]=num[i][j][k+1]+arr[i][j][k];//计算出k~1000中的数总共出现的次数
				arr[i][j][k]=arr[i][j][k+1]+arr[i][j][k]*k;//计算出k~1000中的数总共的高度
			}
		}
	}
	int fx,fy,lx,ly,left,right,middle,answer,tot;
	long long need,p;
	REP(i,1,T)
	{
		scanf("%d%d%d%d%lld",&fx,&fy,&lx,&ly,&need);
		if(Get(fx,fy,lx,ly,1)<need)//如果总共的高度也达不到要求自然是摘不到苹果了
		{
			Cry();
		}
		else
		{
			left=1,right=1000;//这是一个二分
			while(left<=right)
			{
				middle=(right+left)>>1;
				if(Get(fx,fy,lx,ly,middle)>=need)
				{
					answer=middle;//记录答案
					left=middle+1;
				}
				else
				{
					right=middle-1;
				}
			}
			tot=GetCnt(fx,fy,lx,ly,answer);//找到总共的出现次数
			p=Get(fx,fy,lx,ly,answer);
			while(p-answer>=need)//answer的值未必全部取,所以可能需要减去几个
			{
				p-=answer;
				tot--;
			}
			printf("%d\n",tot);//输出答案
		}
	}
}
Part2
前置芝士
- 主席树:这可能才是本题的考点吧.
 
具体做法
在做本题前,建议先完成P3834,如果写过这道题那么思如应该会很清晰,用主席树维护一下前缀每个数出现的次数以及总高度,然后主席树上二分一下,然后...就没有然后了,几乎就是一个模板题了.
代码
int top=1000;
int root[maxN];
struct Tree
{
	int sum,lson,rson;
	long long sum_;
}tree[maxN*32];
int point_cnt=0;
//主席树标准define
#define LSON tree[now].lson
#define RSON tree[now].rson
#define MIDDLE ((left+right)>>1)
#define LEFT LSON,left,MIDDLE
#define RIGHT RSON,MIDDLE+1,right
#define NEW_LSON tree[new_tree].lson
#define NEW_RSON tree[new_tree].rson
void PushUp(int now)
{
	tree[now].sum=tree[LSON].sum+tree[RSON].sum;
	tree[now].sum_=tree[LSON].sum_+tree[RSON].sum_;
}
void Updata(int num,int &new_tree,int now,int left=1,int right=top)//主席树修改,从now到new_tree这颗新的线段树中
{
	if(num<left||right<num)
	{
		new_tree=now;
		return;
	}
	new_tree=++point_cnt;
	if(left==right)
	{
		tree[new_tree].sum=tree[now].sum+1;//出现的次数+1
		tree[new_tree].sum_=tree[now].sum_+num;//总共高度加num
		return;
	}
	Updata(num,NEW_LSON,LEFT);//继续修改
	Updata(num,NEW_RSON,RIGHT);
	PushUp(new_tree);//合并
}
#define SUM tree[now].sum-tree[cut].sum
#define SUM_ tree[now].sum_-tree[cut].sum_
int Query(long long need,int cut,int now,int left=1,int right=top)//查询
{
	if(need<=0)//如果需要的小于等于0自然就是0了
	{
		return 0;
	}
	if(SUM_<=need)//如果需要的大于总共的则全部返回
	{
		return SUM;
	}
	if(left==right)//到也节点处理需要特殊一点
	{
		if(need%left==0)//如果可以除尽
		{
			return need/left;//直接返回
		}
		else
		{
			return need/left+1;//不可以则需要加1
		}
	}
	return Query(need,											tree[cut].rson,RIGHT)//优先找大的,所以先找右子树
		  +Query(need-tree[RSON].sum_+tree[tree[cut].rson].sum_,tree[cut].lson,LEFT);//在查找左子树的时候need需要减去右子树的部分
}
void Solve2()
{
	scanf("%d",&T);
	int num;
	REP(i,1,M)
	{
		scanf("%d",&num);
		Updata(num,root[i],root[i-1]);//直接建树,维护前缀每个数出现的次数和总共高度
	}
	int left,right;
	long long need;
	int air;//没有用的数
	REP(i,1,T)
	{
		scanf("%d%d%d%d%lld",&air,&left,&air,&right,&need);
		if(tree[root[right]].sum_-tree[root[left-1]].sum_<need)//如果摘不到
		{
			Cry();
		}
		else
		{
			printf("%d\n",Query(need,root[left-1],root[right]));//输出答案
		}
	}
}
												
											「Luogu P2468 [SDOI2010]粟粟的书架」的更多相关文章
- Luogu P2468 [SDOI2010]粟粟的书架
		
一道二合一的题目.两部分思维难度都不太高,但是也都很巧妙.尤其是主席树的\(50\)分,由于本人初学主席树,所以没有见过主席树上二分的套路,就被小小的卡了一下.. \(n <= 200\) \( ...
 - 「Luogu P3078 [USACO13MAR]扑克牌型Poker Hands」
		
本题有\(O(N)\)的优秀做法,但是因为在考场上不一定能想到,就来分享一种\(O(N\log_2N)\)的做法.虽然有点慢,但是可以过. 前置芝士 线段树:提高组及以上必备内容,不会的同学可以学习一 ...
 - 「Luogu P3820 小D的地下温泉」
		
这道题的考点比较多. 前置芝士 BFS(DFS),这两种算法在这道题中并没有什么特别突出的地方,基本就是自己看心情写(本文以DFS为准,所以我心情是好是坏呢?) 连通块,可以将每一个温泉看作一个连通块 ...
 - 「Luogu P2253 好一个一中腰鼓!」
		
就这道题的理论难度来说绿题是有点低了,但是这道题的实际难度来看,顶多黄题,所以建议加强数据或出数据升级版. 前置芝士 线段树:具体可以看我的另一篇文章. 具体做法 暴力的方法想必都会,所以来讲一下正解 ...
 - BZOJ1926:[SDOI2010]粟粟的书架——题解
		
http://www.lydsy.com/JudgeOnline/problem.php?id=1926 https://www.luogu.org/problemnew/show/P2468 幸福幼 ...
 - [BZOJ1926][SDOI2010]粟粟的书架
		
BZOJ Luogu Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Cormen 的文章.粟粟家中有一个 R ...
 - bzoj1926[Sdoi2010]粟粟的书架   二分 主席树
		
1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec Memory Limit: 552 MBSubmit: 1064 Solved: 421[Submit][Stat ...
 - bzoj 1926: [Sdoi2010]粟粟的书架 (主席树+二分)
		
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1926 题面; 1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Se ...
 - [bzoj1926][Sdoi2010]粟粟的书架_二分_主席树
		
粟粟的书架 bzoj-1926 Sdoi-2010 题目大意:题目链接 注释:略 想法:分成两个题 前面的我们可以二分,直接二分出来检验即可. 对于R=1的,相当一个数列,我们在上面建立主席树. 然后 ...
 
随机推荐
- php 基础 字符型转换整形
			
示例: 可以得出规律:以有效数字开头的,取有效数字.以非有效数字开头的都转换为0:
 - 安慰奶牛Cheering up the Cow
			
传送门 一次a就很开心 可以当作kruskal模板题(orz --------------------------------------------------------------------- ...
 - [踩坑记录] windows10 应用商店打不开 代码: 0x80131500
			
在某博客看到的方法,供参考,可以尝试一下,我的也是这么解决的1.打开“运行”输入 inetcpl.cpl (“WINDOWS”+“R”键,输入 inetcpl.cpl亦可)2.点开高级往下拉,勾上&q ...
 - TensorFlow:使用inception-v3实现各种图像识别
			
程序来自博客: # https://www.cnblogs.com/felixwang2/p/9190740.html上面这个博客是一些列的,所以可以从前往后逐一练习. # https://www.c ...
 - 消息队列(四)--- RocketMQ-消息发送
			
概述 RocketMQ 发送普通消息有三种 可靠同步发送 可靠异步发送 单向(oneway)发送 :只管发送,直接返回,不等待消息服务器的结果,也不注册回调函数,简单地说,就是只管发,不管信息是否发送 ...
 - Yii2掉index.php?r=
			
普通 首先确认apache2配置 1. 开启 apache 的 mod_rewrite 模块 去掉LoadModule rewrite_module modules/mod_rewrite.so前的“ ...
 - Atcoder Beginner Contest145E(01背包记录路径)
			
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;int a[3007],b[3007];int ...
 - mysql免安装版配置启动时出错
			
今天安装了MySQL5.7的免安装版本,启动时报了服务无法启动的错误,在网上找了好久终于找到了解决方法 我找到解决方法的博客地址是:http://blog.csdn.net/qq_27093465/a ...
 - Ubuntu 安装 uWSGI
			
uWSGI官方网址: https://pypi.org/project/uWSGI/ 使用如下命令安装: pip install uWSGI 报如下错: Collecting uWSGI Using ...
 - 移动端,ajax 动态加载的元素,为动态添加的一系列同个类名的元素添加点击事件
			
背景:一个列表页,有一系列同类名的元素,需要为每一个动态添加的列表项添加事件: 点击选择下图中不同的文档类型,再通过 ajax 动态加载不同的文档. 使用过的方法: 1.通知 jquery 的 $(s ...