Vetor BZOJ4311 (linha de divisão de segmento e conquista, casco convexo)
Assunto
Você precisa manter uma coleção de vetores que suporte as seguintes operações:
-
Inserir um vetor (x, y)
-
Excluir o i-ésimo vetor inserido
-
Consulte o valor máximo do produto escalar do conjunto atual e (x, y). Se a corrente estiver vazia, defina a saída 0
Intervalo de dados
$ n \ 200000, 1 \ le x, y \ le 10 ^ 6 $
Ideias de resolução de problemas
Questão de divisão e conquista de árvore de segmento de linha
Em primeiro lugar, verificou-se que, para uma linha reta em que um vetor está localizado, a inclinação de todas as linhas retas perpendiculares a ele é igual.Uma linha reta passa pelo ponto no conjunto de vetores e a mais à direita é a resposta.Não é difícil encontrar o casco convexo do conjunto de vetores
Cascos convexos não são fáceis de mesclar e não são fáceis de excluir.Considere a segmentação da árvore de segmentos de linha, divida o tempo de cada vetor em segmentos $ log $, pendure na árvore de segmentos de linha e construa um casco convexo em cada ponto da árvore de segmentos de linha e resolva Três pontos podem ser usados para um único casco convexo; a consulta é o valor mínimo de todas as respostas, do nó raiz ao nó folha
Na minha escrita, os pontos são classificados com x antecipadamente, a constante é menor, o casco convexo é solicitado após a construção de um nó
O código é o seguinte
#pragma GCC optimize(3, "inline")
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Pa pair<ll, ll>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;
template <typename T>
void read(T &x) {
x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
for (;isdigit(c);c=getchar()) x=x*10+(c^48);
if (f) x=-x;
}
template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }
template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }
const int N = 300500;
int cnt, cnt2, T, tp;
struct node {
ll x, y, l, r;
bool operator < (const node &i) const {
return x < i.x;
}
}vec[N], v[N];
vector<Pa > poi[N<<2];
Pa st[N];
#define ls p << 1
#define rs ls | 1
void change(int p, int l, int r, Pa x, int L, int R) {
if (L <= l && r <= R) return poi[p].push_back(x), void();
int mid = (l + r) >> 1;
if (L <= mid) change(ls, l, mid, x, L, R);
if (mid < R) change(rs, mid + 1, r, x, L, R);
}
double K(Pa a, Pa b, Pa c) {
return (a.se - b.se) * (a.fi - c.fi) < (a.se - c.se) * (a.fi - b.fi) ;
}
ll Ans(Pa a, Pa b) {
return a.fi * b.fi + a.se * b.se;
}
ll ans[N];
void solve(int p, int l, int r) {
tp = 0;
for (auto x: poi[p]) {
while (tp > 1 && K(st[tp-1], st[tp], x)) tp--;
st[++tp] = x;
}
for (int i = l;i <= r; i++) {
if (!v[i].l) continue;
Pa t = MP(v[i].x, v[i].y);
int L = 1, R = tp, ti = 0;
while (L < R) {
ti++;
int m1 = (L + R) >> 1;
if (Ans(t, st[m1]) < Ans(t, st[m1+1])) L = m1 + 1;
else R = m1;
}
Mx(ans[v[i].l], Ans(t, st[R]));
}
if (l == r) return; int mid = (l + r) >> 1;
solve(ls, l, mid), solve(rs, mid + 1, r);
}
int main() {
freopen ("hs.in","r",stdin);
freopen ("hs.out","w",stdout);
int n; read(n);
for (int i = 1;i <= n; i++) {
int op, x, y;
read(op), read(x);
if (op == 1)
read(y), vec[++cnt] = (node) { x, y, i, n };
else if (op == 2) vec[x].r = i;
else read(y), cnt2++, v[i] = (node) {x, y, cnt2, cnt2};
}
sort(vec + 1, vec + cnt + 1);
for (int i = 1;i <= cnt; i++)
change(1, 1, n, MP(vec[i].x, vec[i].y), vec[i].l, vec[i].r);
solve(1, 1, n);
for (int i = 1;i <= cnt2; i++) printf ("%lld\n", ans[i]);
return 0;
}