#include "shortcut.h"
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
using llong = long long;
const int maxN = 3001;
llong t3[4 * maxN], t4[4 * maxN], lazy3[4 * maxN], lazy4[4 * maxN];
llong t1[4 * maxN], t2[4 * maxN], lazy1[4 * maxN], lazy2[4 * maxN];
vector<llong> x, val;
llong c;
void Build(llong* t, llong* lazy, int v, int vl, int vr, const vector<llong>& a)
{
lazy[v] = 0;
if (vl == vr)
{
t[v] = a[vr];
return;
}
int vm = (vl + vr) / 2;
Build(t, lazy, v * 2, vl, vm, a);
Build(t, lazy, v * 2 + 1, vm + 1, vr, a);
t[v] = max(t[v * 2], t[v * 2 + 1]);
}
inline void Push(llong* t, llong* lazy, int v, int vl, int vr)
{
if (lazy[v])
{
if (vl != vr)
{
lazy[v * 2] += lazy[v];
lazy[v * 2 + 1] += lazy[v];
}
t[v] += lazy[v];
lazy[v] = 0;
}
}
void Add(llong* t, llong* lazy, int v, int vl, int vr, int l, int r, llong val)
{
if (l > vr || vl > r)
return;
if (l <= vl && vr <= r)
{
lazy[v] += val;
return;
}
Push(t, lazy, v, vl, vr);
int vm = (vl + vr) / 2;
Add(t, lazy, v * 2, vl, vm, l, r, val);
Add(t, lazy, v * 2 + 1, vm + 1, vr, l, r, val);
Push(t, lazy, v * 2, vl, vm);
Push(t, lazy, v * 2 + 1, vm + 1, vr);
t[v] = max(t[v * 2], t[v * 2 + 1]);
}
void Add(llong* t1, llong* lazy1, llong* t2, llong* lazy2, int v, int vl, int vr, int l, int r, llong val)
{
if (l > vr || vl > r)
return;
if (l <= vl && vr <= r)
{
lazy1[v] += val;
lazy2[v] += val;
return;
}
Push(t1, lazy1, v, vl, vr);
Push(t2, lazy2, v, vl, vr);
int vm = (vl + vr) / 2;
Add(t1, lazy1, t2, lazy2, v * 2, vl, vm, l, r, val);
Add(t1, lazy1, t2, lazy2, v * 2 + 1, vm + 1, vr, l, r, val);
Push(t1, lazy1, v * 2, vl, vm);
Push(t2, lazy2, v * 2, vl, vm);
Push(t1, lazy1, v * 2 + 1, vm + 1, vr);
Push(t2, lazy2, v * 2 + 1, vm + 1, vr);
t1[v] = max(t1[v * 2], t1[v * 2 + 1]);
t2[v] = max(t2[v * 2], t2[v * 2 + 1]);
}
llong Max(llong* t, llong* lazy, int v, int vl, int vr, int l, int r)
{
if (vl > r || l > vr)
return numeric_limits<llong>::min();
Push(t, lazy, v, vl, vr);
if (l <= vl && vr <= r)
return t[v];
int vm = (vl + vr) / 2;
return max(Max(t, lazy, v * 2, vl, vm, l, r), Max(t, lazy, v * 2 + 1, vm + 1, vr, l, r));
}
llong cache[maxN][maxN];
bool Poss(int s, int e, llong cur)
{
if (cache[s][e] != numeric_limits<llong>::min())
return cache[s][e] <= cur;
multiset<llong> mx;
for (int l = s, r = s - 1; l <= e; ++l)
{
if (r < l)
{
r = l;
mx.clear();
}
else
mx.erase(mx.find(x[l] + val[l]));
while (r + 1 <= e && x[r + 1] - x[l] <= (x[e] - x[s]) - (x[r + 1] - x[l]) + c)
{
++r;
mx.insert(x[r] + val[r]);
}
if (mx.size()) cache[s][e] = max(cache[s][e], *mx.rbegin() - x[l] + val[l]);
}
mx.clear();
for (int i = s; i <= e; ++i)
mx.insert(val[i] - x[i]);
for (int l = s, r = s; ; ++l)
{
while (l > r)
{
mx.erase(mx.find(val[r] - x[r]));
++r;
}
while (r <= e && x[r] - x[l] < (x[e] - x[s]) - (x[r] - x[l]) + c)
{
mx.erase(mx.find(val[r] - x[r]));
++r;
}
if (r > e)
break;
if (mx.size())
cache[s][e] = max(cache[s][e], (x[e] - x[s]) + *mx.rbegin() + x[l] + val[l] + c);
}
return cache[s][e] <= cur;
};
long long Brutos(int n, vector<int> l, vector<int> val, int c)
{
vector<llong> x(n);
for (int i = 1; i < n; ++i)
x[i] = x[i - 1] + l[i - 1];
llong ans = numeric_limits<llong>::max();
for (int l = 0; l < n; ++l)
for (int r = l + 1; r < n; ++r)
{
llong cur = 0;
for (int a = 0; a < n; ++a)
{
cur = max(cur, (llong)val[a]);
for (int b = a + 1; b < n; ++b)
{
if (b <= l || a >= r)
cur = max(cur, val[a] + val[b] + x[b] - x[a]);
else if (a <= l && b >= r)
cur = max(cur, val[a] + val[b] + x[l] - x[a] + x[b] - x[r] + min(x[r] - x[l], (llong)c));
else if (l <= a && b <= r)
cur = max(cur, val[a] + val[b] + min(x[b] - x[a], x[a] - x[l] + x[r] - x[b] + c));
else if (a <= l)
cur = max(cur, val[a] + val[b] + x[l] - x[a] + min(x[b] - x[l], x[r] - x[b] + c));
else if (b >= r)
cur = max(cur, val[a] + val[b] + x[b] - x[r] + min(x[r] - x[a], x[a] - x[l] + c));
}
}
ans = min(ans, cur);
}
return ans;
}
llong lrout[maxN][maxN];
long long find_shortcut(int n, vector<int> l, vector<int> val_, int c_)
{
// cerr << "Brutos: " << Brutos(n, l, val_, c_) << '\n';
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cache[i][j] = lrout[i][j] = numeric_limits<llong>::min();
c = c_;
val.assign(val_.begin(), val_.end());
vector<llong> valc(val.begin(), val.end());
for (llong& x: valc)
x += c;
x.resize(n);
x[0] = 0;
for (int i = 1; i < n; ++i)
x[i] = x[i - 1] + l[i - 1];
vector<llong> pref(n), suff(n), pathpref(n), pathsuff(n);
pref[0] = val[0];
pathpref[0] = val[0];
for (int i = 1; i < n; ++i)
{
pathpref[i] = max(pathpref[i - 1], pref[i - 1] + x[i] + val[i]);
pref[i] = max(pref[i - 1], -x[i] + val[i]);
}
suff.back() = val.back();
pathsuff.back() = val.back();
for (int i = n - 2; i >= 0; --i)
{
pathsuff[i] = max(pathsuff[i + 1], suff[i + 1] + (x.back() - x[i]) + val[i]);
suff[i] = max(suff[i + 1], -(x.back() - x[i]) + val[i]);
}
for (int l = 0; l < n; ++l)
{
Build(t1, lazy1, 1, 0, n - 1, val);
Build(t4, lazy4, 1, 0, n - 1, valc);
vector<llong> valcr = valc;
for (int r = l; r < n; ++r)
valcr[r] += x[r] - x[l];
vector<llong> valr = valc;
for (int r = l; r < n; ++r)
valr[r] += x[r] - x[l];
Build(t2, lazy2, 1, 0, n - 1, valcr);
Build(t3, lazy3, 1, 0, n - 1, valr);
int r = l, m = l, m1 = l;
while (r < n)
{
lrout[l][r] = max(pathsuff[r], pathpref[l]);
while (m <= r && x[m] - x[l] + c < x[r] - x[m])
++m;
while (m1 + 1 <= r && x[m1 + 1] - x[l] <= x[r] - x[m1 + 1] + c)
++m1;
/*if (l == 1 && r == 3)
for (int i = l; i <= r; ++i)
cerr << "tree4[" << i << "] = " << Max(t4, lazy4, 1, 0, n - 1, i, i) << '\n';*/
if (l <= m1 && l)
lrout[l][r] = max(lrout[l][r], Max(t3, lazy3, 1, 0, n - 1, l, m1) + x[l] - x[l - 1] + pref[l - 1] + x[l - 1]);
if (m1 + 1 <= r && l)
lrout[l][r] = max(lrout[l][r], Max(t4, lazy4, 1, 0, n - 1, m1 + 1, r) + x[l] - x[l - 1] + pref[l - 1] + x[l - 1]);
lrout[l][r] = max(lrout[l][r], max(pref[l] + suff[r] + x.back() - (x[r] - x[l]) + min(c, x[r] - x[l]), pathsuff[r]));
if (m <= r && r + 1 < n)
lrout[l][r] = max(lrout[l][r], Max(t1, lazy1, 1, 0, n - 1, m, r) + x[r + 1] - x[r] + suff[r + 1] + (x.back() - x[r + 1]));
if (l <= m - 1 && r + 1 < n)
lrout[l][r] = max(lrout[l][r], Max(t2, lazy2, 1, 0, n - 1, l, m - 1) + x[r + 1] - x[r] + suff[r + 1] + (x.back() - x[r + 1]));
// cerr << "lrout[" << l << "][" << r << "] = " << lrout[l][r] << '\n';
++r;
while (m <= r && x[m] - x[l] + c < x[r] - x[m])
++m;
Add(t1, lazy1, t4, lazy4, 1, 0, n - 1, l, r - 1, x[r] - x[r - 1]);
}
}
llong ans_l = *max_element(val.begin(), val.end()), ans_r = (maxN + 2) * 1000'000'000LL;
llong ans = ans_r + 1;
while (ans_l <= ans_r)
{
llong cur = ans_l + (ans_r - ans_l) / 2;
if (cur == 1)
cerr << "";
bool poss = false;
for (int l = 0; l < n; ++l)
{
int r = l;
while (r < n && lrout[l][r] > cur)
++r;
if (r < n && Poss(l, r, cur))
{
// if (cur == 37)
// cerr << l << " ... " << r << '\n';
poss = true;
break;
}
}
if (poss)
{
ans = cur;
ans_r = cur - 1;
}
else
ans_l = cur + 1;
}
return ans;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
384 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
512 KB |
n = 9, incorrect answer: jury 110 vs contestant 120 |
3 |
Halted |
0 ms |
0 KB |
- |