#include "shortcut.h"
#include "grader.cpp"
#include <deque>
#include "time.h"
#include <random>
#include <iostream>
#include <algorithm>
using namespace std;
mt19937 rnd(22);
const int MAXN = 3005;
const long long inf = 1e16 + 5;
int n;
long long c;
vector <int> l, d;
long long pref[MAXN];
pair <long long, long long> maxMid[MAXN][MAXN];
pair <long long, long long> maxL[MAXN], maxR[MAXN];
long long getDist(int l, int r)
{
if(l>r) swap(l, r);
if(l==r) return 0;
if(l==0) return pref[r-1];
return pref[r-1] - pref[l-1];
}
long long eval22Fast(int start, int finish)
{
long long answer = 0;
deque <int> dq;
long long maxBroken = -inf;
for(int i = start;i<=finish;i++)
{
while(dq.empty()==false && getDist(dq.front(), i)>getDist(start, dq.front())+getDist(i, finish)+c)
{
maxBroken = max(maxBroken, d[dq.front()]+getDist(start, dq.front()));
dq.pop_front();
}
answer = max(answer, maxBroken+getDist(i, finish)+c+d[i]);
if(dq.empty()==false) answer = max(answer, getDist(dq.front(), i)+d[dq.front()]+d[i]);
while(dq.empty()==false && getDist(dq.back(), i)+d[dq.back()]<=d[i]) dq.pop_back();
dq.push_back(i);
}
return answer;
}
long long eval22(int start, int finish)
{
long long maxDist = 0;
for(int i = start;i<=finish;i++)
{
for(int j = i+1;j<=finish;j++)
{
long long dist = d[i] + d[j];
dist += min(getDist(i, j), getDist(start, i) + getDist(j, finish) + c);
maxDist = max(maxDist, dist);
}
}
return maxDist;
}
long long findMax(vector <long long> v)
{
long long maxVal = 0;
for(long long x: v) maxVal = max(maxVal, x);
return maxVal;
}
void evalMaxMid(int i, int j)
{
for(int p = i;p<=j;p++)
{
//left
maxMid[i][j].first = max(maxMid[i][j].first, min(getDist(i, p), getDist(p, j)+c) + ((p==i)?0:d[p]));
//right
maxMid[i][j].second = max(maxMid[i][j].second, min(getDist(p, j), getDist(i, p)+c) + ((p==j)?0:d[p]));
}
}
long long evalShortcut(int start, int finish)
{
evalMaxMid(start, finish);
long long val_11 = maxL[start].second;
long long val_33 = maxR[finish].second;
long long val_13 = maxL[start].first + min(c, getDist(start, finish)) + maxR[finish].first;
long long val_12 = maxL[start].first + maxMid[start][finish].first; //O(n)
long long val_23 = maxR[finish].first + maxMid[start][finish].second; //O(n)
long long val_22 = eval22Fast(start, finish); //O(n^2)
/*
cout << "maxMid: " << maxMid[start][finish].first << " " << maxMid[start][finish].second << '\n';
cout << "val_11: " << val_11 << '\n';
cout << "val_33: " << val_33 << '\n';
cout << "val_13: " << val_13 << '\n';
cout << "val_12: " << val_12 << '\n';
cout << "val_23: " << val_23 << '\n';
cout << "val_22: " << val_22 << '\n';
*/
return findMax({val_11, val_12, val_13, val_22, val_23, val_33});
}
void init()
{
pref[0] = l[0];
for(int i = 1;i<n-1;i++) pref[i] = pref[i-1] + l[i];
maxL[0] = {d[0], d[0]};
for(int i = 1;i<n;i++)
maxL[i] = {max(d[i]*1LL, maxL[i-1].first + getDist(i-1, i)),
max(maxL[i-1].second, maxL[i-1].first + getDist(i-1, i) + d[i])};
maxR[n-1] = {d[n-1], d[n-1]};
for(int i = n-2;i>=0;i--)
maxR[i] = {max(d[i]*1LL, maxR[i+1].first + getDist(i, i+1)),
max(maxR[i+1].second, maxR[i+1].first + getDist(i, i+1) + d[i])};
for(int i = 0;i<n;i++)
for(int j = i;j<n;j++)
maxMid[i][j] = {0, 0};
/*
for(int j = 0;j<n;j++)
{
int ptr = j;
long long maxNormal = 0;
for(int i = j;i>=0;i--)
{
maxMid[i][j].second = 0;
while(ptr-1>=i && getDist(ptr-1, j)<=getDist(i, ptr-1)+c)
{
ptr--;
maxNormal = max(maxNormal, getDist(ptr, j) + d[ptr]);
}
maxMid[i][j].second = max(maxMid[i][j].second, maxNormal);
}
}
for(int i = 0;i<n;i++)
{
for(int j = i;j<n;j++)
{
pair <long long, long long> newVal;
newVal.first = max(maxMid[i][j].first, maxMid[i][j].second+c);
newVal.second = max(maxMid[i][j].second, maxMid[i][j].first+c);
//maxMid[i][j] = newVal;
}
}
*/
}
long long find_shortcut(int _n, vector <int> _l, vector <int> _d, int _c)
{
double startExecution = clock();
n = _n;
l = _l;
d = _d;
c = _c;
init();
int lastBest = -1;
long long answer = inf;
for(int i = 0;i<n-1;i++)
{
int currBest = -1;
long long localMin = inf;
for(int j = max(i, lastBest-1000);j<min(n, lastBest+1000);j++)
{
//cout << i << " ---- " << j << '\n';
//if(getDist(i, j)<=c) continue;
if(double(clock()-startExecution)/CLOCKS_PER_SEC>1.75) return answer;
long long val = evalShortcut(i, j);
answer = min(answer, val);
if(val<=localMin)
{
localMin = val;
currBest = j;
}
//if(val==100) cout << " KKKKKKKKKKKKKKKKKKK " << '\n';
}
//cout << currBest << '\n';
//if(currBest>lastBest) cout << "DEBA " << i << " : " << lastBest << " " << currBest << '\n';
lastBest = currBest;
}
return answer;
}
/*
4 10
10 20 20
0 40 0 30
9 30
10 10 10 10 10 10 10 10
20 0 30 0 0 40 0 40 0
*/
Compilation message
/tmp/ccVO7lut.o: In function `main':
grader.cpp:(.text.startup+0x0): multiple definition of `main'
/tmp/ccq9wO87.o:shortcut.cpp:(.text.startup+0x0): first defined here
collect2: error: ld returned 1 exit status