BZOJ 3203 保护出题人

题目描述

出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了。

参加SDOI2012的小朋友们释放出大量的僵尸,企图攻击铭铭的家。而你作为SDOI2013的参赛者,你需要保护出题人铭铭。

僵尸从唯一一条笔直道路接近,你们需要在铭铭的房门前放置植物攻击僵尸,避免僵尸碰到房子。

第一关,一只血量为a_1a1 点的墦尸从距离房子x_1x1 米处速接近,你们放置了攻击力为y_1y1 点/秒的植物进行防御;第二关,在上一关基础上,僵尸队列排头增加一只血量为a_2a2 点的僵尸,与后一只僵尸距离dd 米,从距离房x_2x2 米处匀速接近,你们重新放置攻击力为y_2y2 点/秒的植物;……;第nn 关,僵尸队列共有nn 只僵尸,相邻两只僵尸距离dd 米,排头僵尸血量为a_nan点,排第二的 僵尸血量a_{n-1}an1 ,以此类推,排头僵尸从距离房子x_nxn 米处匀速接近,其余僵尸跟随排头同时接近,你们重新放置攻击力为y_nyn 点/秒的植物。

每只僵尸直线移动速度均为11 米/秒,由于植物射击速度远大于僵尸移动速度,可忽略植物子弹在空中的时间。所有僵尸同时出现并接近,因此当一只僵尸死亡后,下一只僵尸立刻开始受到植物子弹的伤害。

游戏得分取决于你们放置的植物攻击力的总和\sum \limits _{i=1} ^{n} y_ii=1nyi ,和越小分数越高,为了追求分数上界,你们每关都要放置攻击力尽量小的植物。

作为SDOI2013的参赛选手,你们能保护出题人么?

解析:

我们可以把之前僵尸的血量叠加到第一只僵尸上,距离也叠加到他身上,判断最小的射速把他打死即可,求其中射速最慢的一组累加到答案中去。所以可以得到yi=max(sum[i]-sum[j-1])/(xi+d*(i-j)),可以看成一个斜率的形式。我们令x1=sum[i],x2=sum[j-1],y1=xi+d*i,x2=d*j,求出最大的斜率k=(y1-y2)/(x1-x2)即可。我们可以维护一个下凸壳,如果新加入的直线与栈顶的直线交点在上一个交点左边,将栈顶直线弹出,用三分法求出与当前点组成直线最大斜率即可。

代码:

#include
#include
#include
#include
#define ll long long
#define mid1 l+(r-l)/3
#define mid2 l+(r-l)/3*2
using namespace std;
struct point
{
	double x,y;
}q[100010];
int n,top;
double ans,d;
double sum[100001],xi[100010];
point operator - (point A,point B){return (point){A.x-B.x,A.y-B.y};}
double Cross(point A,point B)
{
	return A.x*B.y-A.y*B.x;
}
double calc(point A)
{
	int l=1,r=top,i;
	double maxn=0,k1,k2;
	while(l+2=2&&Cross(q[top]-q[top-1],x-q[top-1])<=0) top--;
		q[++top]=x;
		x=(point){xi[i]+i*d,sum[i]};
		ans+=calc(x);
	}
	printf("%.0f\n",ans);
	return 0;
}

你可能感兴趣的:(计算几何,三分法)