• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            原題地址

            寫了幾天終于寫出來了……(顯然,我太弱了,請各位神犇不要鄙視)

            在有加點(diǎn)的情況下,動(dòng)態(tài)地維護(hù)凸包,有以下兩種方法:
            <1>維護(hù)上、下凸殼(本沙茶采用的方法):
            凸包可以拆成上、下凸殼,對它們分別維護(hù)。兩個(gè)凸殼均按照下面定義的<關(guān)系(即先x增、再y增)排序,注意,兩個(gè)凸殼的兩端是相同的,均為整個(gè)凸包的最小點(diǎn)與最大點(diǎn),除兩端外,它們沒有公共定點(diǎn)。
            以上凸殼為例,設(shè)目前加進(jìn)去的點(diǎn)是P,則有以下三種情況:
            1)P小于上凸殼的最小點(diǎn)(這里,對于點(diǎn)"(x1, y1)<(x2, y2)"定義為:x1<x2或x1=x2且y1<y2),此時(shí)將P插入上凸殼,并從P開始從小到大遍歷新的上凸殼,將那些旋轉(zhuǎn)方向不對的點(diǎn)刪掉;
            2)P大于上凸殼的最大點(diǎn)(這里,對于點(diǎn)"(x1, y1)>(x2, y2)"定義為:x1>x2或x1=x2且y1>y2),此時(shí)將P插入上凸殼,并從P開始從大到小遍歷新的上凸殼,將那些旋轉(zhuǎn)方向不對的點(diǎn)刪掉;
            3)P位于上凸殼的最小點(diǎn)與最大點(diǎn)之間:此時(shí)找到上凸殼中,小于等于P的最大點(diǎn)L和大于P的最小點(diǎn)R,判斷PL轉(zhuǎn)向PR是否為逆時(shí)針,若為逆時(shí)針,則P在上凸殼外,插入上凸殼,并分別向左右兩個(gè)方向遍歷,將旋轉(zhuǎn)方向不對的點(diǎn)刪掉;
            對于下凸殼,1)和2)一樣,3)反過來搞即可。注意在找前趨L和后繼R的時(shí)候,可以順便判斷出來P是否在上、下凸殼上,若在凸殼上則不插入。
            顯然,這當(dāng)中有插入、刪除、找值的前趨和后繼等操作,因此需要用平衡樹。由于每個(gè)點(diǎn)最多只會(huì)被插入一次、刪除一次,且遍歷就意味著刪除,因此總時(shí)間復(fù)雜度為O(NlogN)。為了加快速度,可以在平衡樹(Splay Tree)中維護(hù)子樹的最小、最大結(jié)點(diǎn)。
            問題是,這種方法寫起來是很復(fù)雜的,因?yàn)橐S護(hù)兩棵平衡樹。

            <2>極角法(Orz!!):
            如果凸包面積大于0,可以在其內(nèi)部選一個(gè)點(diǎn)作為定點(diǎn),然后將凸包上所有點(diǎn)按照到這個(gè)定點(diǎn)的極角遞增排序,用一棵平衡樹維護(hù)。
            加入新點(diǎn)P時(shí),首先得出P到定點(diǎn)的極角,在平衡樹中找到其前趨和后繼,然后作叉積判斷P是否在外部,若不在外部則不插入,否則插入,并且從這個(gè)前趨與這個(gè)后繼開始,分別向兩端刪掉旋轉(zhuǎn)方向不對的多余點(diǎn)。注意,雖然凸包是一個(gè)環(huán),但由于按照極角排序了,在平衡樹中仍只能作為鏈來維護(hù),這樣就會(huì)出現(xiàn),在找前趨和后繼的時(shí)候,如果在兩端找不到,需要循環(huán),到另一端去找,而且在遍歷的時(shí)候,到頭了也要回到另一端。
            這種方法的時(shí)間復(fù)雜度也是O(NlogN),且由于只要維護(hù)一棵平衡樹,代碼量減小了很多(木有必要像下面的爛代碼一樣每個(gè)操作都加上bool _和N多的[_]了,雖然多了點(diǎn)循環(huán)的特判)。

            當(dāng)然,本題是可以不用平衡樹的,而用線段樹——因?yàn)榭梢噪x線。
            還有一個(gè)問題就是本題的維護(hù)面積問題。面積的2倍可以用各邊兩端點(diǎn)關(guān)于任意定點(diǎn)的叉積之和得出,前提是端點(diǎn)按照逆時(shí)針排列(最后結(jié)果的正負(fù)只與端點(diǎn)排列順序有關(guān),與這個(gè)定點(diǎn)在哪無關(guān)),因此,對于有邊加入或刪除的時(shí)候,就可以順便維護(hù)出來,當(dāng)然在有三角形變化的時(shí)候可以直接維護(hù)三角形。

            動(dòng)態(tài)凸包的最主要應(yīng)用就是那些用凸殼或曲線凸殼優(yōu)化的DP,雖然這種DP大多數(shù)時(shí)候只需要維護(hù)上或下凸殼就行了囧……比較典型的應(yīng)用有:
            NOI2007 cash(動(dòng)態(tài)維護(hù)凸殼,但本題可以用分治轉(zhuǎn)成離線,從而直接Graham構(gòu)造解決)
            NOI2009 poet(維護(hù)曲線凸殼,容易證明這種絕對值P次函數(shù)的曲線符合交點(diǎn)只有一個(gè)的性質(zhì),且對稱軸是越來越右,所以可以直接用隊(duì)列維護(hù)……MS它是一種有用模型的代表)
            BZOJ2149 拆遷隊(duì)(由于合法決策要滿足三個(gè)條件:決策階段較小、A值較小、F值嚴(yán)格比目前階段F值小1,因此需要變序,按照A的遞增序插入決策射線,維護(hù)可以離散化后用線段樹,也可以根據(jù)A值即為斜率且遞增,直接用棧維護(hù)凸殼。當(dāng)然,本題也需要分治轉(zhuǎn)成離線)
            CEOI2011 ballons(本題的效果值曲線為頂點(diǎn)在X軸上的開口向上的拋物線,由于對稱軸x是遞增的,所以可以只維護(hù)右半部分,一個(gè)決策插入后影響的是一個(gè)區(qū)間,可以離散化后用線段樹解決。當(dāng)然,本題如果對稱軸x不遞增才好玩呢囧……)

            代碼:
            #include <iostream> 
            #include 
            <stdio.h> 
            #include 
            <stdlib.h> 
            #include 
            <string.h> 
            using namespace std; 
            #define re(i, n) for (int i=0; i<n; i++) 
            #define re1(i, n) for (int i=1; i<=n; i++) 
            #define re2(i, l, r) for (int i=l; i<r; i++) 
            #define re3(i, l, r) for (int i=l; i<=r; i++) 
            #define rre(i, n) for (int i=n-1; i>=0; i--) 
            #define rre1(i, n) for (int i=n; i>0; i--) 
            #define rre2(i, r, l) for (int i=r-1; i>=l; i--) 
            #define rre3(i, r, l) for (int i=r; i>=l; i--) 
            #define ll long long 
            const int MAXN = 100010
            struct poi { 
                ll x, y; 
                
            bool operator< (poi p0) const {return x < p0.x || x == p0.x && y < p0.y;} 
                
            bool operator> (poi p0) const {return x > p0.x || x == p0.x && y > p0.y;} 
                poi 
            operator- (poi p0) {return (struct poi) {x - p0.x, y - p0.y};} 
            }; 
            struct node { 
                poi v; 
                
            int c[2], p, sz, minNo, maxNo; 
                
            bool d; 
            } T[
            2][MAXN]; 
            int N[2], root[2]; 
            ll res; 
            void sc(bool _, int _p, int _c, bool _d) 

                T[_][_p].c[_d] 
            = _c; T[_][_c].p = _p; T[_][_c].d = _d; 

            void upd(bool _, int No) 

                
            int lch = T[_][No].c[0], rch = T[_][No].c[1]; 
                T[_][No].sz 
            = T[_][lch].sz + T[_][rch].sz + 1
                T[_][No].minNo 
            = lch ? T[_][lch].minNo : No; T[_][No].maxNo = rch ? T[_][rch].maxNo : No; 

            void rot(bool _, int No) 

                
            int p = T[_][No].p; bool d = T[_][No].d; 
                
            if (p == root[_]) T[_][root[_] = No].p = 0else sc(_, T[_][p].p, No, T[_][p].d); 
                sc(_, p, T[_][No].c[
            !d], d); sc(_, No, p, !d); upd(_, p); 

            void splay(bool _, int No, int r) 

                
            int p; while ((p = T[_][No].p) != r) if (T[_][p].p == r) rot(_, No); else if (T[_][p].d == T[_][No].d) rot(_, p), rot(_, No); else rot(_, No), rot(_, No); upd(_, No); 

            void ins(bool _, poi v0) 

                
            if (!root[_]) { 
                    T[_][root[_] 
            = ++N[_]].p = 0; T[_][N[_]].c[0= T[_][N[_]].c[1= 0; T[_][N[_]].sz = 1; T[_][N[_]].minNo = T[_][N[_]].maxNo = N[_]; T[_][N[_]].v = v0; return
                } 
                poi v; 
            int i = root[_], j; 
                
            while (1) { 
                    v 
            = T[_][i].v; T[_][i].sz++; j = T[_][i].c[v0 > v]; if (j) i = j; else break
                } 
                T[_][
            ++N[_]].c[0= T[_][N[_]].c[1= 0; T[_][N[_]].sz = 1; T[_][N[_]].v = v0; T[_][N[_]].minNo = T[_][N[_]].maxNo = N[_]; sc(_, i, N[_], v0 > v); 
                splay(_, N[_], 
            0); 

            int uni(bool _, int A, int B) 

                
            if (!A) return B; else if (!B) return A; else if ((A + B) & 1) { 
                    
            int S = uni(_, A, T[_][B].c[0]); 
                    sc(_, B, S, 
            0); upd(_, B); return B; 
                } 
            else { 
                    
            int S = uni(_, T[_][A].c[1], B); 
                    sc(_, A, S, 
            1); upd(_, A); return A; 
                } 

            int L(bool _, poi v0) 

                
            int i = root[_], j, res0 = -1; poi v; 
                
            while (1) { 
                    v 
            = T[_][i].v; 
                    
            if (v0 < v) j = T[_][i].c[0]; else if (v0 > v) {j = T[_][i].c[1]; res0 = i;} else return i; 
                    
            if (j) i = j; else break
                } 
                
            return res0; 

            int R(bool _, poi v0) 

                
            int i = root[_], j, res0 = -1; poi v; 
                
            while (1) { 
                    v 
            = T[_][i].v; 
                    
            if (v0 < v) {j = T[_][i].c[0]; res0 = i;} else if (v0 > v) j = T[_][i].c[1]; else return i; 
                    
            if (j) i = j; else break
                } 
                
            return res0; 

            ll cr(poi p0, poi p1) 

                
            return p0.x * p1.y - p0.y * p1.x; 

            void solve(poi p) 

                
            int _L = L(0, p); if (_L >= 0 && !(T[0][_L].v < p || p < T[0][_L].v)) return
                
            int _R = R(0, p), _L0, _R0, _; bool FF; ll cr0; 
                
            if (_L == -1) { 
                    res 
            += cr(T[0][_R].v, p); FF = 1
                } 
            else if (_R == -1) { 
                    res 
            += cr(p, T[0][_L].v); FF = 1
                } 
            else { 
                    cr0 
            = cr(T[0][_L].v - p, T[0][_R].v - p); 
                    
            if (cr0 > 0) {res += cr0; FF = 1;} else FF = 0
                } 
                
            if (FF) { 
                    ins(
            0, p); 
                    
            while (_L = T[0][root[0]].c[0]) { 
                        _L0 
            = T[0][_L].maxNo; splay(0, _L0, root[0]); _L = T[0][root[0]].c[0]; 
                        
            if (T[0][_L].c[0]) _L0 = T[0][T[0][_L].c[0]].maxNo; else break
                        cr0 
            = cr(T[0][_L].v - p, T[0][_L0].v - p); 
                        
            if (cr0 <= 0) {res -= cr0; _ = uni(0, T[0][_L].c[0], T[0][_L].c[1]); sc(0, root[0], _, 0); upd(0, root[0]);} else break
                    } 
                    
            while (_R = T[0][root[0]].c[1]) { 
                        _R0 
            = T[0][_R].minNo; splay(0, _R0, root[0]); _R = T[0][root[0]].c[1]; 
                        
            if (T[0][_R].c[1]) _R0 = T[0][T[0][_R].c[1]].minNo; else break
                        cr0 
            = cr(T[0][_R].v - p, T[0][_R0].v - p); 
                        
            if (cr0 >= 0) {res += cr0; _ = uni(0, T[0][_R].c[0], T[0][_R].c[1]); sc(0, root[0], _, 1); upd(0, root[0]);} else break
                    } 
                } 
                _L 
            = L(1, p); if (_L >= 0 && !(T[1][_L].v < p || p < T[1][_L].v)) returnelse _R = R(1, p); 
                
            if (_L == -1) { 
                    res 
            += cr(p, T[1][_R].v); FF = 1
                } 
            else if (_R == -1) { 
                    res 
            += cr(T[1][_L].v, p); FF = 1
                } 
            else { 
                    cr0 
            = cr(T[1][_L].v - p, T[1][_R].v - p); 
                    
            if (cr0 < 0) {res -= cr0; FF = 1;} else FF = 0
                } 
                
            if (FF) { 
                    ins(
            1, p); 
                    
            while (_L = T[1][root[1]].c[0]) { 
                        _L0 
            = T[1][_L].maxNo; splay(1, _L0, root[1]); _L = T[1][root[1]].c[0]; 
                        
            if (T[1][_L].c[0]) _L0 = T[1][T[1][_L].c[0]].maxNo; else break
                        cr0 
            = cr(T[1][_L].v - p, T[1][_L0].v - p); 
                        
            if (cr0 >= 0) {res += cr0; _ = uni(1, T[1][_L].c[0], T[1][_L].c[1]); sc(1, root[1], _, 0); upd(1, root[1]);} else break
                    } 
                    
            while (_R = T[1][root[1]].c[1]) { 
                        _R0 
            = T[1][_R].minNo; splay(1, _R0, root[1]); _R = T[1][root[1]].c[1]; 
                        
            if (T[1][_R].c[1]) _R0 = T[1][T[1][_R].c[1]].minNo; else break
                        cr0 
            = cr(T[1][_R].v - p, T[1][_R0].v - p); 
                        
            if (cr0 <= 0) {res -= cr0; _ = uni(1, T[1][_R].c[0], T[1][_R].c[1]); sc(1, root[1], _, 1); upd(1, root[1]);} else break
                    } 
                } 

            int main() 

                
            int m; poi p0, p1, p2, _; 
                scanf(
            "%lld%lld%lld%lld%lld%lld%d"&p0.x, &p0.y, &p1.x, &p1.y, &p2.x, &p2.y, &m); 
                
            if (p1 < p0) {_ = p0; p0 = p1; p1 = _;} if (p2 < p0) {_ = p0; p0 = p2; p2 = _;} if (p2 < p1) {_ = p1; p1 = p2; p2 = _;} 
                ins(
            0, p0); ins(0, p2); ins(1, p0); ins(1, p2); ll __ = cr(p0 - p1, p2 - p1); 
                
            if (__ > 0) ins(0, p1); else if (__ < 0) ins(1, p1); 
                res 
            = __ >= 0 ? __ : -__; 
                re(i, m) { 
                    scanf(
            "%lld%lld"&_.x, &_.y); 
                    solve(_); 
                    printf(
            "%lld\n", res >= 0 ? res : -res); 
                } 
                
            return 0
            }
            亚洲欧美成人久久综合中文网 | 国产国产成人久久精品| 日韩精品久久久久久| 精品国产青草久久久久福利 | 国产精品综合久久第一页 | 国产成人精品三上悠亚久久| 亚洲人成精品久久久久| 99久久久精品免费观看国产| 亚洲国产成人久久精品影视| 香蕉久久永久视频| 国产综合久久久久| 欧美日韩中文字幕久久久不卡| 久久精品久久久久观看99水蜜桃| 久久婷婷国产综合精品| 久久人妻少妇嫩草AV蜜桃| 久久国产热精品波多野结衣AV| 久久人妻少妇嫩草AV蜜桃| 久久国产热精品波多野结衣AV| 久久久网中文字幕| 久久综合九色综合精品| 亚洲色婷婷综合久久| 久久一本综合| 精品免费久久久久国产一区| 国产精品久久久久无码av| 久久精品国产2020| 亚洲国产精品一区二区三区久久| 97久久久久人妻精品专区| 久久精品亚洲AV久久久无码| 最新久久免费视频| 四虎影视久久久免费| 久久精品中文字幕有码| Xx性欧美肥妇精品久久久久久| 97精品久久天干天天天按摩| 色婷婷综合久久久久中文| 亚洲狠狠婷婷综合久久蜜芽| 亚洲国产一成人久久精品| 亚洲精品乱码久久久久久蜜桃不卡 | 久久久精品久久久久久 | 久久免费视频1| 久久亚洲AV无码精品色午夜麻豆| 热RE99久久精品国产66热|