Cod sursa(job #671713)

Utilizator crushackPopescu Silviu crushack Data 31 ianuarie 2012 19:45:16
Problema Euro Scor 5
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.97 kb
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <set>
#define NMax 34577
using namespace std;

const char IN[]="euro.in",OUT[]="euro.out";
const double eps=0.0001;

struct point{
	double x;
	double y;
};
struct line{
	point a;
	point b;
};

double abs(double x){
	return x<0 ? -x : x;
}
double cross(point const &a,point const &b,point const &c){
	return (a.x*(b.y-c.y) + b.x*(c.y-a.y) + c.x*(a.y-b.y))/2.;
}
int sgn(double x){
	return x<0 ? -1 : ((x==0) ? 0 : 1);
}
double panta(line const &a){
	return (a.b.y-a.a.y)/(a.b.x-a.a.x);
}

struct cmp{
	bool operator()(line const &A,line const &B){
		return panta(A)<panta(B);
	}
};

int N,T;
int v[NMax] , D[NMax] , S[NMax];
set<line,cmp> s;

inline void coef(line const &A,double &a,double &b,double &c){
	a=A.b.y-A.a.y;
	b=A.a.x-A.b.x;
	c=A.a.x*a + A.a.y*b;
}

point intersect(line const &A,line const &B){
	double a,b,c,a2,b2,c2;
	
	coef(A,a,b,c);
	coef(B,a2,b2,c2);
	
	point ret= { (c*b2 - c2*b)/(a*b2 - a2*b) , (c*a2 - c2*a)/(b*a2-b2*a) };
	return ret;
}

double val(line const &A,double y){
	double a,b,c;
	
	coef(A,a,b,c);
	return (c-a*y)/b;
}

bool paralele(line const &A,line const &B){
	double a1,b1,c1,a2,b2,c2;
	
	coef(A,a1,b1,c1);
	coef(B,a2,b2,c2);
	
	return abs(a1*b2-a2*b1)<eps;
}

void addline(double a,double b) // y=ax+b
{
	line qline;
	point p1,p2,p3,p4;
	
	qline.a.x=1;
	qline.a.y=a+b;
	qline.b.x=N;
	qline.b.y=N*a+b;
	
	if (s.size()==0)
	{
		s.insert(qline);
		return;
	}
	
	if (s.size()==1)
	{
		if (paralele(*s.begin(),qline))
		{
			if (val(qline,1)>val(*s.begin(),1))
			{
				s.clear();
				s.insert(qline);
			}
			return;
		}
		
		( val(*s.begin(),1)>val(qline,1) ) ? (p1=s.begin()->a,p3=qline.b) : (p1=qline.a,p3=s.begin()->b);
		p2=intersect(*s.begin(),qline);
		
		s.clear();
		
		qline.a=p1; qline.b=p2; s.insert(qline);
		qline.a=p2; qline.b=p3; s.insert(qline);
		return;
	}
	
	set<line,cmp>::iterator it=s.lower_bound(qline),p,pp;
	
	for (p=it;sgn(cross(qline.a,qline.b,p->a))==-1 && p!=s.begin();--p);
	for (pp=it;sgn(cross(qline.a,qline.b,pp->b))==-1 && pp!=s.end();++pp);
	if (pp==s.end()) --pp;
	if (p==pp) return;
	
	p1=p->a;
	p2=intersect(*p,qline);
	p3=intersect(qline,*pp);
	p4=pp->b;
	
	s.erase(p,pp);
	
	qline.a=p1; qline.b=p2; s.insert(qline);
	qline.a=p2; qline.b=p3; s.insert(qline);
	qline.a=p3; qline.b=p4; s.insert(qline);
}

void solve()
{
	int i;
	
	D[1]=S[1]-T;
	addline(-S[1],D[1]);
	
	for (i=2;i<=N;++i)
	{
		double a,b,c;
		fprintf(stderr,"%d\n",s.size());
		while (s.begin()->b.x<i) s.erase(s.begin());
		coef(*s.begin(),a,b,c);
		int y=(int)floor((c-a*i)/b);
		
		D[i]=i*S[i] - T + y;
		
		addline(-S[i],D[i]);
	}
}

int main()
{
	int i;
	freopen(IN,"r",stdin);
	scanf("%d%d",&N,&T);
	for (i=1;i<=N;++i)
		scanf("%d",v+i),S[i]=S[i-1]+v[i];
	fclose(stdin);
	
	solve();
	
	freopen(OUT,"w",stdout);
	printf("%d\n",D[N]);
	fclose(stdout);
	
	return 0;
}