Pagini recente » Cod sursa (job #2016581) | Cod sursa (job #1290925) | Cod sursa (job #1373564) | Cod sursa (job #1168868) | Cod sursa (job #2742291)
#include<bits/stdc++.h>
#define INF 1000000000000000
using namespace std;
ifstream f("euro.in");
ofstream g("euro.out");
long long v[34570],s[34570],dp[34570];
struct line
{
long long a,b;
};
line dq[34570];
long long calc_y(line p,int x)//calculeaza valoare lui y in punctul x pe o dreapta
{
return p.a*x+p.b;
}
long double calc_x(line p1,line p2)//calculeaza x ul intersectiei celor 2 drepte
{
//y=a1*x+b1
//y=a2*x+b2
//x=(b2-b1)/(a1-a2)
if(p1.a>p2.a)
return INF;
if(p1.a==p2.a)
{
if(p1.b>=p2.b)
return INF;
return -INF;
}
return (long double)(p2.b-p1.b)/(p1.a-p2.a);
}
bool useless(line linie1,line linie2,line linie3)//verifica daca linia 2 e useless(<=> linia 3 o sa se intersecteze cu linia 1 inainte de intersectia lui 1 cu linia 2 si astfel linia 2 nu o sa mai fie minim niciodata)
{
if(calc_x(linie1,linie2)>=calc_x(linie1,linie3))
return 1;
return 0;//if(calc(linie1,linie2)<calc(linie1,linie3)) -> asa e normal
}
int main()
{
long long n,i,t,st=1,dr=0;
line linie;
f>>n>>t;
for(i=1;i<=n;i++)
f>>v[i],s[i]=s[i-1]+v[i];
//panta nu e monotona pe masura ce creste i -> tot putem face deque pe maxime :) , doar ca mai trebuie o conditie in plus
//merge convex hull trick pt ca i e crescator (sau ce argument e acolo in formula)
dp[0]=0;
dq[++dr]={0,0};
for(i=1;i<=n;i++)
{
while(st<dr&&calc_x(dq[st],dq[st+1])<=i)//daca linia 1 nu o sa mai fie maxima cand ajunge la i (pana acolo o sa ii ia locul linia 2)
st++;
dp[i]=calc_y(dq[st],i)+s[i]*i-t;
linie={-s[i],dp[i]};
while(st<dr&&useless(dq[dr-1],dq[dr],linie)==1)
dr--;
dq[++dr]=linie;
// while(st<dr&&calc_x(dq[dr-1],dq[dr])<=i&&dq[dr-1].a>=dq[dr].a)//daca linia 2 nu e mai buna decat linia 1
// dr--;
}
g<<dp[n];
return 0;
}