#include "shortcut.h"
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
using llong = long long;
const int maxN = 3000;
const int lg = 11;
llong t1[lg + 1][maxN], t2[lg + 1][maxN], t3[lg + 1][maxN], t4[lg + 1][maxN];
vector<llong> x, val;
llong c;
inline int e_lg(int a)
{
static vector<int> cache = []() -> vector<int> {
vector<int> res(maxN);
for (int i = 1; i < res.size(); ++i)
res[i] = __lg(i);
return res;
}();
return cache[a];
}
void Build(llong t[][maxN], const vector<llong>& a)
{
int n = a.size();
for (int i = 0; i < n; ++i)
t[0][i] = a[i];
for (int l = 1; l <= lg; ++l)
for (int i = 0; i < n; ++i)
t[l][i] = max(t[l - 1][i], t[l - 1][i + (2 << l)]);
}
inline llong Max(llong t[][maxN], int l, int r)
{
int i = e_lg(r - l + 1);
return max(t[i][l], t[i][r - (1 << i) + 1]);
}
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);
}
if (cache[s][e] == numeric_limits<llong>::min())
++cache[s][e];
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)
{
vector<llong> valcr = valc;
for (int r = l; r < n; ++r)
valcr[r] += x[r] - x[l];
vector<llong> valr = val;
for (int r = l; r < n; ++r)
valr[r] += x[r] - x[l];
Build(t2, valcr);
Build(t3, valr);
int r = l, m = l, m1 = l;
while (r < n)
{
lrout[l][r] = max(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, l, m1) + 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 (l <= m - 1 && r + 1 < n)
lrout[l][r] = max(lrout[l][r], Max(t2, 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;
}
}
for (int r = n - 1; r >= 0; --r)
{
vector<llong> vals = val;
for (int i = 0; i <= r; ++i)
vals[i] += x[r] - x[i];
Build(t1, vals);
vals = val;
for (int i = 0; i <= r; ++i)
vals[i] += x[r] - x[i] + c;
Build(t4, vals);
int l = r, m = r, m1 = r;
while (l >= 0)
{
lrout[l][r] = max(lrout[l][r], max(pathsuff[r], pathpref[l]));
while (m - 1 >= l && x[r] - x[m - 1] <= x[m - 1] - x[l] + c)
--m;
while (m1 >= l && x[m1] - x[l] > x[r] - x[m1] + 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 (m1 + 1 <= r && l)
lrout[l][r] = max(lrout[l][r], Max(t4, m1 + 1, r) + x[l] - x[l - 1] + pref[l - 1] + x[l - 1]);
if (m <= r && r + 1 < n)
lrout[l][r] = max(lrout[l][r], Max(t1, m, r) + x[r + 1] - x[r] + suff[r + 1] + (x.back() - x[r + 1]));
// cerr << "lrout[" << l << "][" << r << "] = " << lrout[l][r] << '\n';
--l;
}
}
llong ans = (maxN + 2) * 1000'000'000LL + 1LL;
for (int l = 0; l < n; ++l)
for (int r = l; r < n; ++r)
{
Poss(l, r, 0);
ans = min(ans, max(lrout[l][r], cache[l][r]));
}
return ans;
}
Compilation message
shortcut.cpp: In lambda function:
shortcut.cpp:19:27: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i = 1; i < res.size(); ++i)
~~^~~~~~~~~~~~
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
5 ms |
512 KB |
n = 4, 80 is a correct answer |
2 |
Incorrect |
5 ms |
640 KB |
n = 9, incorrect answer: jury 110 vs contestant 100 |
3 |
Halted |
0 ms |
0 KB |
- |