Cod sursa(job #8417)

Utilizator filipbFilip Cristian Buruiana filipb Data 24 ianuarie 2007 19:00:00
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.33 kb
#include <stdio.h>
#include <algorithm>
#include <set>
#define EPS 1e-5
#define NMax 35000

using namespace std;

double eps=1e-8;

struct line { 
              long long a, b; 
              line(){}
              line(long long t1, long long t2):a(t1), b(t2){}
            };

int N, T;
long long S[NMax], M[NMax];
set<line> s;
line last_line;
double last_x;

bool operator<(const line& l1, const line& l2)
{ return l1.b < l2.b; }

double xinter(const line& l1,const line& l2)
{
       return double(l1.a-l2.a)/double(l2.b-l1.b);
}

double yinter(const line& l1,double x)
{
       return l1.b*x+l1.a;
}

double best(double x)
{
       double ans=-1e12;
       set<line>::iterator it=s.find(last_line);
       while (it!=s.end() && yinter(*it,x)>ans){
               ans=yinter(*it,x);
               ++it;
       }
       --it;
       last_x=x;
       last_line=*it;
       return ans;
}

void insereaza(const line& l)
{
       while (true){
               set<line>::iterator it1=s.lower_bound(l);
               if (it1==s.end())
                       break;
               set<line>::iterator it2=it1;++it2;
               if (it2==s.end())
                       break;
               if (it1->b==l.b){
                       if (it1->a<=l.a){
                               s.erase(it1);
                               continue;
                       }
                       return;
               }
               double x=xinter(*it1,*it2);
               if (yinter(l,x)<yinter(*it1,x)-eps)
                       break;
               s.erase(it1);
       }
       while (true){
               set<line>::iterator it1=s.upper_bound(l);
               if (it1==s.begin())
                       break;
               --it1;
               if (it1==s.begin())
                       break;
               set<line>::iterator it2=it1;--it2;
               if (it1->b==l.b){
                       if (it1->a<=l.a){
                               s.erase(it1);
                               continue;
                       }
                       return;
               }
               double x=xinter(*it1,*it2);
               if (yinter(l,x)<yinter(*it1,x)-eps)
                       break;
               s.erase(it1);
       }
       set<line>::iterator it1=s.lower_bound(l);
       if (it1!=s.end() && it1!=s.begin()){
               set<line>::iterator it2=it1;--it2;
               double x=xinter(*it1,*it2);
               if (yinter(l,x)<=yinter(*it1,x)+eps)
                       return;
       }
       s.insert(l);
       if (s.size()==1){
               last_line=l;
               last_x=-1e12;
       }
       else if (s.find(last_line)==s.end())
               last_line=l;
       else if (yinter(last_line,last_x)<yinter(l,last_x))
               last_line=l;
}

int main(void)
{
    int i, x;
    
    freopen("euro.in", "r", stdin);
    freopen("euro.out", "w", stdout);
    
    scanf("%d %d", &N, &T);
    for (i = 1, S[0] = 0; i <= N; i++)
    {
        scanf("%d", &x);
        S[i] = x + S[i-1];
    }
    
    insereaza(line(0, 0));
    for (i = 1; i <= N; i++)
    {
        M[i] = S[i] * i - T + (long long)best(i);
        
        insereaza(line(M[i], -S[i]));
    }
    
    printf("%lld\n", M[N]);
    
    
    return 0;
}