Cod sursa(job #486200)

Utilizator freak93Adrian Budau freak93 Data 20 septembrie 2010 18:48:28
Problema Euro Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3 kb
#include<fstream>
#include<set>
#include<cassert>

using namespace std;

const char iname[]="euro.in";
const char oname[]="euro.out";
const int maxn=360000;

ifstream f(iname);
ofstream g(oname);

long long a[maxn],s[maxn],maxt,rez,dp[maxn],zi[maxn],ok,x;

int i,n,t;

struct maxv
{
    bool operator()(const int &x,const int &y)
    {
        long long v=dp[x]-s[x]*i-dp[y]+s[y]*i;
        if(v==0)
            return s[x]>s[y];
        return v<0;
    }
};
struct zile
{
    bool operator()(const int &x,const int &y)
    {
        return zi[x]<zi[y];
    }
};
set<int,zile> R;
set<int,maxv> S;

int main()
{
    f>>n>>t;
    for(i=1;i<=n;++i)
        f>>a[i],s[i]=s[i-1]+a[i];
    maxt=rez=0;
    S.insert(0);
    for(i=1;i<=n;++i)
    {
        set<int,maxv>::iterator it,jt;
        x=*(S.rbegin());
        dp[i]=dp[x]+(s[i]-s[x])*i-t;
        it=S.insert(i).first;
        ok=1;

        //Trebuie eliminat :?
        jt=it;
        jt++;
        if(jt!=S.end())
            if(s[*it]>=s[*jt])
            {
                S.erase(it);
                ok=0;
            }
        //daca nu
        if(ok)
        {
            //scaotem ratia
            //scoate alea cu crestere mai mica
            while(it!=S.begin())
            {
                jt=it;
                jt--;
                if(s[*jt]>=s[i])
                    R.erase(*jt),S.erase(jt);
                else
                    break;
            }
            //adaugam ratia de crestere inapoi
            it=S.find(i);
            if(it!=S.begin())
            {
                jt=it;
                jt--;
                R.erase(*jt);
                x=dp[*it]-dp[*jt];
                x=x/(s[*it]-s[*jt])+1;
                zi[*jt]=x;
          //      assert(x>i);
                R.insert(*jt);
                if(S.find(*jt)==S.end())
                    assert(0);
            }
            //adaugam ratia de crestere inainte
            jt=it;
            ++it;
            if(it!=S.end())
            {
                x=dp[*it]-dp[*jt];
                x=x/(s[*it]-s[*jt])+1;
           //     assert(x>i);
                R.erase(*jt);
                zi[*jt]=x;
                R.insert(*jt);
              //  assert(S.find(*jt)!=S.end());
            }
        }
      //  for(set<int,maxv>::iterator it=S.begin();it!=S.end();++it)
       //     fprintf(stderr,"%d ",*it);
       // printf("\n");
        while(R.size()>0&&zi[*R.begin()]<=i+1)
        {
            x=*R.begin();
            R.erase(x);
            it=S.find(x);
            if(it==S.end())
                continue;
            jt=it;
            ++jt;
            if(dp[*it]-s[*it]*(i+1)>=dp[*jt]-s[*jt]*(i+1))
                R.erase(*jt),S.erase(jt);
            //adaugam ratia in fata
            jt=it;
            ++it;
            if(it==S.end())
                continue;
            x=dp[*it]-dp[*jt];
            x=x/(s[*it]-s[*jt])+1;
         //   if(x<=i)
          //      assert(s[*it]>s[*jt]);
            zi[*jt]=x;
            R.insert(*jt);
        }
    }
    g<<dp[n]<<"\n";
}