Fie A
o mulțime de N
puncte Ai
în plan de coordonate întregi cunoscute (Ai.x, Ai.y)
. Pentru o întrebare definită printr-un punct Q=(Q.x, Q.y)
se cere aria înfășurătorii convexe a punctelor: {Q} ∪ {Ai | Ai.x < Q.x și Ai ∈ A }
.
Înfășurătoarea convexă a unei mulțimi de puncte este poligonul convex de arie minimă care conține toate punctele în interior sau pe laturile acestuia.
Cerinţă
Determinați răspunsurile pentru M
întrebări de tipul enunţat mai sus, relativ la mulțimea inițială A
.
Date de intrare
Pe prima linie a fişierului geometrie.in
se află numerele naturale nenule N
și M
.
Următoarele N
linii conțin câte două numere Ai.x Ai.y
separate printr-un spațiu.
Următoarele M
linii conțin câte două numere Q.x Q.y
separate printr-un spațiu.
În fișierul de intrare atât punctele Ai
cât și punctele Q
sunt în ordinea crescătoare a valorilor x
.
Date de ieşire
În fişierul geometrie.out
vor fi M
linii care conțin răspunsurile la întrebări, în ordinea în care au fost cerute, fiecare pe câte o linie. Afişaţi fiecare număr cu o zecimală precizie.
Restricţii şi precizări
N, M ≤ 10^5
- Toate coordonatele
Ai.x
,Ai.y
,Qx
șiQy ≤ 10^9
- Punctele din mulțimea
A
au valoriXi
distincte. - Înfășurătoarea convexă a unei mulțimi cu cel mult două puncte are aria egală cu zero.
- Pentru teste în valoare de 20 puncte
N ≤ 3
- Pentru teste în valoare de 40 puncte
N×M ≤ 10^3
- Pentru teste în valoare de 60 puncte
N×M ≤ 10^6
Exemplul 1
geometrie.in
3 3 1 3 4 5 5 1 3 3 6 8 8 4
geometrie.out
0.0 15.0 14.5
Exemplul 2
geometrie.in
9 2 1 3 3 5 4 1 6 4 8 6 9 1 10 3 11 5 13 2 4 3 10 4
geometrie.out
3.0 32.0
Explicație
Poligoanele formate din punctele care se obțin pentru cele doua întrebări de la exemplul 2 sunt:
Cum e corect?
cout < "As la info";
cout << "As la info";
cout >> "As la info";
Felicitări! Poți mai mult?
Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.
Greșit, dar nu-i bai!
Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.
Rezolvare
Iată rezolvarea de 100 de puncte pentru problema Geometrie:
/*
Time complexity: O(M * log N), ~100 points
Paul Diac
*/
#include <stdio.h>
#include <stdlib.h>
#define NMax 100000
#define MMax 100000
#define llong long long
FILE *fin = fopen("geometrie.in", "rt");
FILE *fout = fopen("geometrie.out", "wt");
typedef struct point {
int x, y;
} point;
int N, M;
point a[NMax], q[NMax];
long long area(point a, point b, point c) {
return (llong) a.x * b.y + (llong) a.y * c.x + (llong) b.x * c.y
- (llong) a.x * c.y - (llong) a.y * b.x - (llong) b.y * c.x; }
long long areaTrap(point a, point b) { // 'below' trapezoid area, doubled, a.x < b.x
return (llong) (b.x - a.x) * (a.y + b.y);
}
typedef struct stack {
point p[NMax];
llong aLeft[NMax]; // area on left side, below
int top;
} stack;
stack up, dn; // up and down stack
int getTangent(stack &st, point q, int sgn) {
int pi = st.top, step;
for (step = 1; step < pi; step <<= 1);
for (; step; step>>=1) {
if (pi-step-1 >= 0 && area(q, st.p[pi-step], st.p[pi-step-1]) * sgn < 0) {
pi -= step;
}
}
for (; pi > 0 && area(q, st.p[pi], st.p[pi-1]) * sgn < 0; pi--);
return pi;
}
llong solveQuery(point q) { // stacks must have CH points with x < q.xlim
if (up.top == 0) {
return 0;
}
int upi = getTangent(up, q, 1);
int dni = getTangent(dn, q, -1);
llong rez = 0;
rez += up.aLeft[upi];
rez -= dn.aLeft[dni];
rez += areaTrap(up.p[upi], q);
rez -= areaTrap(dn.p[dni], q);
return rez;
}
void addPointToStack(stack &st, point p, int sign) {
for (; st.top > 0 && area(p, st.p[st.top], st.p[st.top-1]) * sign < 0; st.top--);
// no need to bsearch here, amortized complexity is linear
st.aLeft[st.top+1] = st.aLeft[st.top] + areaTrap(st.p[st.top], p);
st.p[++st.top] = p;
}
void solve() {
up.p[0] = a[0];
dn.p[0] = a[0];
int ai = 0, qi = 0; // A[] set and query idx
for (ai = 1; ai < N || qi < M; ai++) {
// answers queries with q[i].x <= a[ai].x
for (; qi < M && q[qi].x <= a[ai].x; qi++) {
fprintf(fout, "%.1lf\n", (double) solveQuery(q[qi]) / 2);
}
if (ai < N) {
// add point a[ai] to stacks
addPointToStack(up, a[ai], 1);
addPointToStack(dn, a[ai], -1);
}
}
}
int main() {
fscanf(fin, "%d %d", &N, &M);
for (int i = 0; i < N; i++) {
fscanf(fin, "%d %d", &a[i].x, &a[i].y);
}
for (int i = 0; i < M; i++) {
fscanf(fin, "%d %d", &q[i].x, &q[i].y);
}
solve();
fclose(fin);
fclose(fout);
return 0;
}
Atenție
Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa .
Rezolvarea problemei #1166 Geometrie
Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #1166 Geometrie de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.
Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!