이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
#define ST first
#define ND second
#define PB push_back
using namespace std;
using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;
const int nax = 200 * 1000 + 10;
int n;
int a[nax], b[nax], f[nax], g[nax];
struct Point {
ll x, y;
int id;
};
Point lines[nax];
ll ans;
vector<Point>S1, S2;
int ptr;
bool intersect(Point&x, Point&y, Point&z) {
return (z.x - x.x) * (y.y - x.y) - (y.x - x.x)*(z.y - x.y) <= 0;
}
ll get_mx(vector<Point>&vec, int x) {
if((int)vec.size() == 0) return -1;
while((int)vec.size() >= 2 && (ll)vec.back().x * x + vec.back().y <= (ll)vec[(int)vec.size() - 2].x * x + vec[(int)vec.size() - 2].y) {
vec.pop_back();
}
return (ll)vec.back().x * x + vec.back().y;
}
ll get_mx2(int x) {
if((int)S2.size() == 0) return -1;
while(ptr + 1 < (int)S2.size() && S2[ptr+1].x * x + S2[ptr+1].y >= S2[ptr].x * x + S2[ptr].y) {
ptr++;
}
return S2[ptr].x * x + S2[ptr].y;
}
void rec(int l, int r) {
int mid = ((l + r) >> 1);
if(l <= mid - 1) rec(l, mid - 1);
if(mid + 1 <= r) rec(mid + 1, r);
f[mid] = a[mid];
g[mid] = b[mid];
lines[mid] = {g[mid], (ll)g[mid] * mid, mid};
for(int i = mid - 1; i >= l; --i) {
f[i] = min(f[i + 1], a[i]);
g[i] = min(g[i + 1], b[i]);
lines[i] = {g[i], (ll)g[i] * (-i + 1), i};
}
for(int i = mid + 1; i <= r; ++i) {
f[i] = min(f[i - 1], a[i]);
g[i] = min(g[i - 1], b[i]);
lines[i] = {g[i], (ll)g[i] * i, i};
}
int lp, rp, l2, r2;
rp = r;
for(lp = l; lp <= mid; ++lp) {
while(rp >= mid && (f[lp] > f[rp] || g[lp] > g[rp])) {
rp--;
}
if(rp >= mid) {
ans = max(ans, (ll)f[lp] * g[lp] * (rp - lp + 1));
}
}
lp = l;
for(rp = r; rp >= mid; rp--) {
while(lp <= mid && (f[rp] > f[lp] || g[rp] > g[lp])) {
lp++;
}
if(lp <= mid) {
ans = max(ans, (ll)f[rp] * g[rp] * (rp - lp + 1));
}
}
// --------------------------
rp = r;
r2 = r;
S1.clear(); S2.clear();
ptr = 0;
for(lp = l; lp <= mid; lp++) {
while(r2 - 1 >= mid && (g[lp] >= g[r2 - 1])) {
r2--;
if((int)S1.size() >= 1 && S1.back().x == lines[r2].x) continue;
while((int)S1.size() >= 2 && intersect(S1.back(), lines[r2], S1[(int)S1.size() - 2])) {
S1.pop_back();
}
S1.PB(lines[r2]);
// add
}
while(rp >= mid && (f[lp] > f[rp])) {
rp--;
// erase
if((int)S2.size() == 0) {
while((int)S1.size() > 0) {
S2.PB(S1.back());
S1.pop_back();
}
ptr = 0;
}
if(S2.back().id == rp + 1) {
S2.pop_back();
// must add points
}
}
if(rp >= mid && g[lp] >= g[r2] && r2 <= rp) {
// [r2, rp]
ll w1 = get_mx(S1, -lp + 1);
ll w2 = get_mx2(-lp + 1);
ans = max(ans, max(w1,w2) * f[lp]);
}
}
// ---------------------------
lp = l;
l2 = l;
lines[mid] = {(ll)g[mid], (ll)g[mid] * (-mid + 1), mid};
S1.clear(); S2.clear();
ptr = 0;
for(rp = r; rp >= mid; rp--) {
while(l2 + 1 <= mid && (g[rp] >= g[l2 + 1])) {
l2++;
if((int)S1.size() >= 1 && S1.back().x == lines[l2].x) continue;
while((int)S1.size() >= 2 && intersect(S1.back(), lines[l2], S1[(int)S1.size() - 2])) {
S1.pop_back();
}
S1.PB(lines[l2]);
// add
}
while(lp <= mid && (f[rp] > f[lp])) {
lp++;
if((int)S2.size() == 0) {
while((int)S1.size() > 0) {
S2.PB(S1.back());
S1.pop_back();
}
ptr = 0;
}
if(S2.back().id == lp - 1) {
S2.pop_back();
// must add points
}
}
if(lp <= mid && g[rp] >= g[l2] && lp <= l2) {
// [r2, rp]
// ans = max(ans, ask(lp, l2, rp) * f[rp]);
ll w1 = get_mx(S1, rp);
ll w2 = get_mx2(rp);
ans = max(ans, max(w1,w2) * f[rp]);
}
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for(int i = 0; i < n; ++i) {
cin >> a[i] >> b[i];
}
rec(0, n - 1);
cout << ans;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |