Ben are un teren pe care se află o pădure cu arbori seculari. Acolo vrea să-şi construiască o cabană, însă el fiind ecologist nu vrea să taie niciun arbore, ci vrea să găsească cea mai mare suprafaţă dreptunghiulară fără arbori. El caută o suprafaţă dreptunghiulară străjuită doar în colţuri de arbori şi cu laturile paralele cu axele de coordonate. Ben cunoaşte coordonatele tuturor arborilor din pădure şi vă roagă să-l ajutaţi să găsească aria dreptunghiului cu suprafaţă maximă care are arbori doar în cele patru colțuri.
Cerința
Cunoscând numărul arborilor din pădure şi coordonatele acestora, se cere să se determine aria dreptunghiului de suprafaţă maximă cu copaci doar în cele 4
colţuri, unde Ben intenţionează să-şi construiască cabana.
Date de intrare
Fișierul de intrare cabana.in
conține pe prima linie un număr natural n
, reprezentând numărul de arbori din pădure. Pe fiecare dintre următoarele n
linii se află două numere întregi, separate printr-un spațiu, ce reprezintă abscisa și ordonata unui arbore.
Date de ieșire
Fișierul de ieșire cabana.out
va conține pe prima linie pe prima linie numărul natural a
, reprezentând aria dreptunghiului de suprafață maximă.
Restricții și precizări
- Pentru 10% din teste:
1 ≤ n ≤ 10
,-10^3 ≤ x ≤ 10^3
,-10^3 ≤ y ≤ 10^3
- Pentru 30% din teste:
1 ≤ n ≤ 500
,-10^3 ≤ x ≤ 10^3
,-10^3 ≤ y ≤ 10^3
- Pentru 50% din teste:
1 ≤ n ≤ 500
,-10^6 ≤ x ≤ 10^6
,-10^6 ≤ y ≤ 10^6
- Pentru 70% din teste:
1 ≤ n ≤ 3000
,-10^9 ≤ x ≤ 10^9
,-10^9 ≤ y ≤ 10^9
- Pentru 100% din teste:
1 ≤ n ≤ 50000
,-10^9 ≤ x ≤ 10^9
,-10^9 ≤ y ≤ 10^9
- Nu există doi arbori așezați pe aceeași poziție.
Exemplu
cabana.in
22 6 25 25 22 15 5 23 23 6 7 11 16 11 20 10 22 6 16 12 6 7 19 10 19 10 14 7 14 7 7 18 14 18 7 10 7 19 19 29 19 29 4 19 4
cabana.out
150
Explicație
Coordonatele dreptunghiului de arie maximă cu laturile paralele cu axele de coordonate şi care nu conţine arbori decât în colţuri sunt:
19 19
29 19
29 4
19 4
deci aria maximă este 150
.
#include <bits/stdc++.h> using namespace std; ifstream fin ("cabana.in"); ofstream fout("cabana.out"); #define maxn 150010 #define inf 1000000001 struct punct { int x,y,i; }v[maxn], v1[maxn], v2[maxn]; bool cmp1 (punct a, punct b) { if (a.x == b.x) return a.y > b.y; return a.x < b.x; } bool cmp2 (punct a, punct b) { if (a.y == b.y) return a.x < b.x; return a.y > b.y; } int bit[maxn], whichL[maxn], whichC[maxn], posL[maxn], posC[maxn], pointer[maxn]; int sq, p, nr1, nr2, t, n; vector<int> C[maxn], L[maxn]; void create_structure() { sq = sqrt(nr1); v[0].y = -inf; int maxpoint = 0; t = 0; for (int i = 1; i <= nr1; ++i) { if (v[C[i][0]].y > v[maxpoint].y) maxpoint = C[i][0]; if (i % sq == 0) { ++t; bit[t] = maxpoint; maxpoint = 0; } } } void update (int pos) { int whbit = (pos-1)/sq+1; if (whbit > t) return; int maxpoint = 0; for (int i = (whbit-1)*sq + 1; i <= whbit*sq; ++i) { if (v[C[i][pointer[i]]].y > v[maxpoint].y) maxpoint = C[i][pointer[i]]; } bit[whbit] = maxpoint; } int query (int left, int right) { int maxpoint = 0; if (right - left + 1 <= sq) { for (int i = left; i <= right; ++i) { if (v[C[i][pointer[i]]].y > v[maxpoint].y) { maxpoint = C[i][pointer[i]]; } } p = whichC[maxpoint]; return v[maxpoint].y; } int whleft = (left-1)/sq+1; int whright = (right-1)/sq+1; for (int i = whleft+1; i <= whright-1; ++i) { if (v[bit[i]].y > v[maxpoint].y) maxpoint = bit[i]; } for (int i = left; i <= whleft*sq; ++i) { if (v[C[i][pointer[i]]].y > v[maxpoint].y) { maxpoint = C[i][pointer[i]]; } } for (int i = (whright-1)*sq +1; i <= right; ++i) { if (v[C[i][pointer[i]]].y > v[maxpoint].y) { maxpoint = C[i][pointer[i]]; } } p = whichC[maxpoint]; return v[maxpoint].y; } int main() { fin >> n; for (int i = 1; i <= n; ++i) { fin >> v[i].x >> v[i].y; v1[i].x = v[i].x; v1[i].y = v[i].y; v2[i].x = v[i].x; v2[i].y = v[i].y; v1[i].i = i; v2[i].i = i; } sort(v1+1, v1+n+1, cmp1); sort(v2+1, v2+n+1, cmp2); v1[0].x = -inf; for (int i=1 ; i <= n; ++i) { if (v1[i].x != v1[i-1].x) { ++nr1; } C[nr1].push_back(v1[i].i); whichC[v1[i].i] = nr1; posC[v1[i].i] = C[nr1].size()-1; } v2[0].y = inf; for (int i =1 ; i <= n; ++i) { if (v2[i].y != v2[i-1].y) { ++nr2; } L[nr2].push_back(v2[i].i); whichL[v2[i].i] = nr2; posL[v2[i].i] = L[nr2].size()-1; } for (int i = 1; i <= nr1; ++i) { pointer[i] = 0; C[i].push_back(0); } create_structure(); long long answer = 0; int cnt = 0; while (query(1,nr1) != -inf) { ++cnt; punct LU = v[C[p][pointer[p]]]; int whcol = p; int poscol = pointer[p]; int whline = whichL[C[p][pointer[p]]]; int posline = posL[C[p][pointer[p]]]; if (posline + 1 < L[whline].size() && poscol + 1 < C[whcol].size()-1) { int rightp = L[whline][posline+1]; int downp = C[whcol][poscol+1]; punct RU = v[rightp]; punct LD = v[downp]; int newcol = whichC[rightp]; int posnewcol = posC[rightp]; int newline = whichL[downp]; int posnewline = posL[downp]; if (posnewcol + 1 < C[newcol].size()-1 && posnewline + 1 < L[newline].size() && C[newcol][posnewcol+1] == L[newline][posnewline+1]) { punct RD = v[C[newcol][posnewcol+1]]; int rez = query(whcol+1, newcol-1); if (rez < RD.y) { answer = max(answer, 1LL*(RD.x - LD.x)*(RU.y - RD.y)); } } } ++pointer[whcol]; update(whcol); } fout << answer; }