【bzoj3203】[Sdoi2013]保护出题人 凸包+二分

题目描述

输入

第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离。接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近。

输出

一个数,n关植物攻击力的最小总和 ,保留到整数。

样例输入

5 2
3 3
1 1
10 8
4 8
2 3

样例输出

7



题解

凸包+二分

把第 $i$ 只僵尸的血量看作前 $i$ 只僵尸的血量的前缀和,那么就相当于所有僵尸同时受到伤害。

把僵尸的距离堪称 $x$ ,血量看成 $y$ ,要求的就是 $\frac yx$ 的最大值。显然最大值一定在上凸壳上取到,因此维护凸壳,在凸壳上二分即可。

然而每次加入的僵尸位置是队头,相当于把所有后面僵尸的血量都加上 $a_i$ 。我们不能实现整体加减,因此需要平移原点。调整距离同理。

时间复杂度 $O(n\log n)$

#include <cstdio>
typedef long double ld;
struct point
{
	ld x , y;
	point() {}
	point(ld a , ld b) {x = a , y = b;}
}sta[100010] , O(0 , 0) , P;
int top;
inline ld slop(point a , point b)
{
	return (b.y - a.y) / (b.x - a.x);
}
int main()
{
	int n , i , l , r , mid , ret;
	ld a , x = 0 , y , d , ans = 0;
	scanf("%d%Lf" , &n , &d);
	for(i = 1 ; i <= n ; i ++ )
	{
		scanf("%Lf%Lf" , &a , &y) , P = point(O.x + x - d , O.y);
		while(top > 1 && slop(P , sta[top]) < slop(P , sta[top - 1])) top -- ;
		sta[++top] = P;
		O.x -= y + d - x , O.y -= a;
		ret = 1 , l = 2 , r = top;
		while(l <= r)
		{
			mid = (l + r) >> 1;
			if(slop(O , sta[mid]) > slop(O , sta[mid - 1])) ret = mid , l = mid + 1;
			else r = mid - 1;
		}
		ans += slop(O , sta[ret]) , x = y;
	}
	printf("%.0Lf\n" , ans);
	return 0;
}

原文地址:https://www.cnblogs.com/GXZlegend/p/8137127.html

时间: 2024-11-08 18:42:07

【bzoj3203】[Sdoi2013]保护出题人 凸包+二分的相关文章

bzoj3203: [Sdoi2013]保护出题人 凸包+三分

/************************************************************** Problem: 3203 User: wangyucheng Language: C++ Result: Accepted Time:344 ms Memory:4396 kb ****************************************************************/ #include<iostream> #include&l

BZOJ3203 SDOI2013 保护出题人 凸包+三分法

题意:给定N组询问和D,初始时集合为空,每组询问先向集合的开头插入一个元素xi,然后给出一个数pi,求最小的yi使得\[{y}_{i}\left({p}_{i}+D\left(i-1 \right) \right)\geq {x}_{i}\] 题解:设Si=$\sum\limits_{j = 1}^i{x}_{j}$,显然yi=$max\left \{ \frac{{S}_{i}-{S}_{j-1}}{x_{i}+D\left ( i-j \right )} \right \},1\leq j\

BZLJ 3203 Luogu P3299 [SDOI2013]保护出题人 (凸包、斜率优化、二分)

惊了,我怎么这么菜啊.. 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=3203 (luogu)https://www.luogu.org/problemnew/show/P3299 题解: 先讲正常做法. 设\(S_i\)为\(i\)的前缀和,则显然第\(i\)次答案为\(\max^i_{j=1} \frac{S_i-S_{j-1}}{x_i+id-jd}\) 那么很显然就是要求从一个点\((x_i+id,S_i)\)

[bzoj3203][Sdoi2013]保护出题人

人生第一道三分?... 把进攻序列里的前i只僵尸看成一个点,横坐标是第i只僵尸到达的时间,纵坐标是这i只僵尸的血量总和..就是说植物必须在这段时间内输出这些伤害..那么单位时间的输出伤害就是斜率了. 问题就变成了对于若干个点,求从原点到各个点斜率的最大值. 因为D是固定的,而每次新加入僵尸实际就是把原来的点平移..并且相对位置关系不变...所以显然斜率最大的点一定在凸包上= = 每次就新加入一个点并维护凸包,然后三分找出凸包上的点与原点连线斜率的最大值(原点与凸包上各个点连线的斜率是单峰的)就好

BZOJ 3203 Sdoi2013 保护出题人 凸包+三分

题目大意:太长自己看 令sumi表示第i个僵尸以及之前的僵尸的体力总和.disi表示第i个僵尸与房屋的初始距离 我们发现我们能消灭一个僵尸当且仅当y>=sumidisi 那么我们要求的显然就是max{sumidisi} 我们将一个僵尸抽象成一个点sumidisi.那么我们发现每一个回合僵尸之间的相对位置是不变的 因此我们能够维护一个凸包.三分就可以 #include <cstdio> #include <cstring> #include <iomanip> #i

【BZOJ3203】[Sdoi2013]保护出题人 二分+凸包

[BZOJ3203][Sdoi2013]保护出题人 Description Input 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近. Output 一个数,n关植物攻击力的最小总和 ,保留到整数. Sample Input 5 2 3 3 1 1 10 8 4 8 2 3 Sample Output 7 HINT 第

SDOI2013 保护出题人

Description ?出题人铭铭认为给SDOI2012 出题太可怕了,因为总要被骂,于是他又给SDOI2013 出题了. 参加SDOI2012 的小朋友们释放出大量的僵尸,企图攻击铭铭的家.而你作为SDOI2013的参赛者,你需要保护出题人铭铭. 僵尸从唯一一条笔直道路接近,你们需要在铭铭的房门前放置植物攻击僵尸,避免僵尸碰到房子.第一关,一只血量为a1 点的僵尸从距离房子x1 米处匀速接近,你们放置了攻击力为y1 点/秒的植物进行防御:第二关,在上一关基础上,僵尸队列排头增加一只血量为a2

bzoj-3203 保护出题人

题意: 在一个诡异的植物大战僵尸游戏中,给出n关: 第i关队首僵尸距房门xi,两个僵尸之间间隔为d: 每次在队首添加一个血量为ai的僵尸,其他僵尸不变: 每关在门前放一个攻击力任意的植物,求n关放置植物总攻击力的最小值: n<=100000,其他数据<=10^12: 题解: 题意叙述略诡异..建议还是去看一眼原题: 首先考虑对于每一关的答案,应该是恰好将最难打死的僵尸打死的攻击力值: 令s[i]为i这个僵尸血量与它前面僵尸血量之和,dis[i]为这个僵尸距房门的距离: 那么答案就是ans=ma

保护出题人「SDOI 2013」

题意 有n个关卡,每一关都会在僵尸队列的排头添加一只僵尸,同时排头与家的距离会发生变化.相邻僵尸之间的距离固定为\(d\). 对于每一关,可以放置一颗任意攻击力的植物(每颗植物仅作用于当前关卡).求攻击力总和最小值. 思路 显然\(f[i]=max(\frac{sum[i]-sum[j-1]}{x[i]+d*(i-j)})\),由于斜率没有单调性,所以二分凸包. 另注:题目的取整指的是四舍五入而不是向下取整,恶臭. 代码 #include <bits/stdc++.h> using names