Vetor BZOJ4311 (linha de divisão de segmento e conquista, casco convexo)

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:

  1. Inserir um vetor (x, y)

  2. Excluir o i-ésimo vetor inserido

  3. 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;
}

Acho que você gosta

Origin www.cnblogs.com/Hs-black/p/12757860.html
Recomendado
Clasificación