bzoj-3203 保护出题人

题意:

在一个诡异的植物大战僵尸游戏中,给出n关;

第i关队首僵尸距房门xi,两个僵尸之间间隔为d;

每次在队首添加一个血量为ai的僵尸,其他僵尸不变;

每关在门前放一个攻击力任意的植物,求n关放置植物总攻击力的最小值;

n<=100000,其他数据<=10^12;

题解:

题意叙述略诡异。。建议还是去看一眼原题;

首先考虑对于每一关的答案,应该是恰好将最难打死的僵尸打死的攻击力值;

令s[i]为i这个僵尸血量与它前面僵尸血量之和,dis[i]为这个僵尸距房门的距离;

那么答案就是ans=max(s[i]/dis[i]);

将这个东西视为一个二维坐标系下的点,要求的就是这个点集与原点斜率最大的地方;

这里我是维护一个上凸壳来二分(为啥别人都是下凸壳);

二分详细还是见代码吧。。我最近各种姿势都有些奇怪;

上凸壳的原因似乎比较显然吧,上凸出来的一个东西可以是答案而下凹进去的绝对不可能啊;

这样对于一个答案的处理就可以做到logn了吧;

但是两关之间的转移,如果一个一个移动点是O(n)的,就又退化到了暴力;

所以不能移动点,移动坐标轴!

然后这题似乎就没啥说的了,最后一句吐槽,我并不想保护出题人;

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
using namespace std;
typedef long long ll;
int st[N],top;
ll x[N],y[N];
double slope(int l,int r)
{
	if(!r)	return -1e100;
	if(x[l]==x[r])
		return y[l]<y[r]?1e100:-1e100;
	return (double(y[l]-y[r]))/(x[l]-x[r]);
}
int main()
{
	int n,i,j,k,l,r,mid;
	ll d,a,xi,lastx;
	double ans=0;
	scanf("%d%lld",&n,&d);
	lastx=d;
	for(i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a,&xi);
		x[0]-=d+xi-lastx;
		y[0]-=a;
		lastx=xi;
		x[i]=x[0]+xi;
		y[i]=y[0]+a;
		while(top>1&&slope(st[top],st[top-1])>=slope(i,st[top]))
			st[top--]=0;
		st[++top]=i;
		l=1,r=top;
		while(l<=r)
		{
			mid=l+r>>1;
			if(slope(0,st[mid])>slope(0,st[mid-1]))
				l=mid+1;
			else
				r=mid-1;
		}
		ans+=slope(0,st[r]);
	}
	printf("%.0lf",ans);
	return 0;
}
时间: 2024-10-06 08:03:49

bzoj-3203 保护出题人的相关文章

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

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

SDOI2013 保护出题人

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

【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 第

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

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

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是固定的,而每次新加入僵尸实际就是把原来的点平移..并且相对位置关系不变...所以显然斜率最大的点一定在凸包上= = 每次就新加入一个点并维护凸包,然后三分找出凸包上的点与原点连线斜率的最大值(原点与凸包上各个点连线的斜率是单峰的)就好

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\

【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$ 只僵尸的血量的前缀和,那么就相当于所有僵尸同时受到伤害. 把僵尸的

保护出题人「SDOI 2013」

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