Cod sursa(job #356282)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 14 octombrie 2009 00:26:17
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.32 kb
/*
Author : Andrei-Bogdan Antonescu
Time Complextity : O(N * log N) 
Memory Complexity : O(2 * N)
*/
using namespace std;

#include <set>
#include <map>
#include <list>
#include <deque>
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <bitset>
#include <utility>
#include <iomanip>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>

#define pb push_back
#define size(V) ((int)(V.size()))
#define f first
#define s second
#define II inline
#define ll long long
#define db double
#define FORit(it, x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); ++it)
#define REP(i, N) for (int i = 0; i < (int)(N); ++i)
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define all(v) v.begin() , v.end()
#define CC(v) memset((v),0,sizeof((v)))
#define CP(v,w) memcpy((v),(w),sizeof((w)))
#define mp make_pair
#define oo (1LL<<62)

#define IN "euro.in"
#define OUT "euro.out"
#define N_MAX 1<<16

typedef vector<int> VI;
typedef pair<int,int> pi;
typedef vector<string> VS;
template<class T> string toString(T n) {ostringstream ost;ost<<n;ost.flush();return ost.str();}
typedef vector<string> VS;

int N,T,A[1<<18];
ll C[N_MAX],D[N_MAX],S[N_MAX];

II void scan()
{
	freopen(IN,"r",stdin);
	freopen(OUT,"w",stdout);
	scanf("%d%d",&N,&T);
	
	FOR(i,1,N)
		scanf("%lld",C+i);
}

II ll get(int k,int x)
{
	if(x < k || k==-1)
		return -oo;
	return C[k-1] + (ll)(x - k + 1) * D[k-1] - (ll)T;
}

II void update(int nod,int st,int dr,int k,int x,int y)
{
	if(x <= st && dr <= y)
	{
		A[nod] = k;
		return;
	}
	
	int mij = (st+dr) >> 1;
	int ln = (nod<<1);
	int rn = ln+1;
	
	if(x <= mij)
		update(ln,st,mij,k,x,y);
	if(y > mij)
		update(rn,mij+1,dr,k,x,y);
	if(A[ln] != A[rn])
		A[nod] = -1;
}

II ll querry(int nod,int st,int dr,int x)
{
	if(st==dr)
		return get(A[nod],x);
	
	int mij = (st+dr) >> 1;
	int ln = (nod<<1);
	int rn = ln+1;
	
	if(A[nod] != -1)
		A[ln] = A[rn] = A[nod];

	if(x <= mij)
		return querry(ln,st,mij,x);
	return querry(rn,mij+1,dr,x);
}

II bool find(int k,int &mx,int &my)
{
	int st(k),dr(N),m,step;
	bool ok(false);
	
	for(m = (st+dr) >> 1;!ok && st < dr;)
	{
		m = ( max(k,st) + dr) >> 1;
		ll dif1 = get(k,m) - querry(1,1,N,m);
		ll dif2 = m == N ? -oo : get(k,m+1) - querry(1,1,N,m+1);
		
		if(dif1 > 0 || dif2 > 0)
			m += (dif2 > 0),ok = true;
		if(dif1 < dif2)
			st = m+1;
		else
			dr = m-1;
	}
	if(get(k,m) < querry(1,1,N,m) )
		return false;
	mx = my = m;
	
	for(step = 1;step <= N;step <<= 1);
	for(mx = m;step;step >>= 1)
		if(mx - step >= k && get(k,mx-step) > querry(1,1,N,mx-step) )
			mx -= step;
	
	for(step = 1;step <= N;step <<= 1);
	for(my = m;step;step >>= 1)
		if(my + step <= N && get(k,my+step) > querry(1,1,N,my+step) )
			my += step;
	return true;
}

II void solve()
{
	FOR(i,1,N) S[i] = S[i-1] + C[i];
	FOR(i,0,N) D[i] = S[N] - S[i];

	memset(A,-1,sizeof(A));
	memset(C,-100,sizeof(C));
	C[0] = 0;
	
	FOR(i,1,N)
	{
		int mx,my;
		if( find(i,mx,my) != false)
			update(1,1,N,i,mx,my);
		C[i] = querry(1,1,N,i);
	}
	
//	FOR(i,1,N)
//		printf("%I64d\n",C[i]);
//	printf("\n");
	CP(S,C);
	
	printf("%lld\n",C[N]);
}

int main()
{
	scan();
	solve();
	return 0;
}