【BZOJ】【P3203】【Sdoi2013】【保护出题人】【题解】【凸包+三分】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3203

iwtwiioi的题解,简要说明一点,“前边所有僵尸的”是指在编号的前边,即相对位置的后面

而且……此题答案可能非常大,输出的时候要学出题人printf("%.0lf\n",ans);而不能是cout<<(long long)ans<<endl;

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
const double eps=1e-18;
struct Point{
	double x,y;
	Point(double _x=0,double _y=0):
		x(_x),y(_y){}
	Point operator+(Point A)const{return Point(x+A.x,y+A.y);}
	Point operator-(Point A)const{return Point(x-A.x,y-A.y);}
}ch[maxn];
double Cross(Point A,Point B){return A.x*B.y-A.y*B.x;}
int n;double d,a[maxn],x[maxn],ans;
double K(Point A,Point B){return (A.y-B.y)/(A.x-B.x);}
int main(){
	scanf("%d%lf",&n,&d);
	for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i],&x[i]);
	int top=0;
	double sum=0;
	for(int i=1;i<=n;i++){
		Point p(i*d,sum);sum+=a[i];
		while(top>1&&Cross(p-ch[top-1],ch[top]-ch[top-1])>=-eps)top--;
		ch[++top]=p;p=Point(x[i]+i*d,sum);
		int l=1,r=top,mid1,mid2;
		while(r-l>=3){
			mid1=l+(r-l)/3;
			mid2=r-(r-l)/3;
			if(K(ch[mid1],p)<K(ch[mid2],p))
				l=mid1;
			else r=mid2;		
		}double res=0;
		for(int j=l;j<=r;j++)res=max(res,K(ch[j],p));
		ans+=res;
	}printf("%.0lf\n",ans);
	return 0;
}


你可能感兴趣的:(bzoj)