CF70D(動態凸包)

2022-05-06 16:03:13 字數 1472 閱讀 3863

給出q(<=1e5)個詢問,每次在加上乙個點,維護凸包,或者詢問某個點是否在凸包內(在邊上也算)。

聽說可以用cdq做……但是並不會。我等蒟蒻只會用平衡樹做。

首先,假設已經維護出了某個點按照極角排序的凸包,那麼對於加入的乙個點,我們首先要查詢它是在凸包內還是凸包外(這個功能也可以用於題目中的查詢)。o表示極角排序的原點,next表示極角排序的下乙個點,pre則表示上乙個點:

那麼,如果p在凸包外,a\(\times\)b就是正數,若p在凸包內a\(\times\)b則是非正整數。

接著,我們要維護凸包。維護凸包依然要查詢next和pre:

類似於gramham,不斷通過刪除next和pre維護凸包凸性。形象理解一下,可以看成p點伸出了兩個筷子,不停嘗試夾住凸包(凸包:喵喵喵?)

注意判斷點是否在凸包內時,有個小坑點。o點必須選擇在凸包內,既不能選擇在凸包外也不能選擇在凸包的邊上。

#include #include #include using namespace std;

typedef long long ll;

const ll maxn=1e5+5;

double ox=0, oy=0;

struct point

void getangle()

}p[maxn];

point operator +(const point &a, const point &b)

point operator -(const point &a, const point &b)

ll operator *(const point &a, const point &b)

bool operator

iter pre(iter x)

bool in(iter x)

void add(point &x)

while (s.size()>3&&(*nxt(it)-*it)*(*nxt(nxt(it))-*nxt(it))<=0) //神仙操作*2

s.erase(nxt(it)); //注意加上=0以後,要判斷size以免遇到兩個點的情況

while (s.size()>3&&(*pre(it)-*it)*(*pre(pre(it))-*pre(it))>=0) //神仙操作*3

s.erase(pre(it));

}bool query(point &x)

int main()

return 0;

}

動態維護凸包

依次插入n個點,詢問凸包面積。利用granham思想,維護凸包,水平序要維護兩個凸殼,比較麻煩,所以用極角序,每次查入用平衡樹維護極角離他最近的點,此時到雙向鍊錶上開始模擬granham雙向刪點,直到無法刪為止,因為每個點至多刪一次,所以是nlogn的複雜度。面積維護用叉積即時維護即可。依次插入n個...

CF1142C U2(計算幾何,凸包)

題目大意 平面上有 n 個點,第 i 個點是 x i,y i 問有多少條拋物線 二次項係數為 1 經過這些點中不同的兩個點,並且內部 不含邊界 沒有任何這些點。重合的拋物線只算一次。1 le n le 10 5,x i y i le 10 6 這題特別有趣。考慮把拋物線方程重寫 y x 2 bx c...

BZOJ 3707 圈地 (動態凸包)

傳送門 題意 給n 個點,求最小三角形。n 1000 題解 好題啊。後面有動態凸包 有一種簡單的做法 首先如果選定了底邊的兩點,那麼還需要選擇一條離這條底邊最近的點。將當前座標系y軸旋轉這條底邊,那麼選擇 x 最小的點。考慮按照斜率從小到大列舉底邊。對於兩個點a,b 來說,若一條底邊c,d 的斜率小...