• <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>
            隨筆 - 97, 文章 - 22, 評論 - 81, 引用 - 0
            數據加載中……

            PKU 1177 Picture

            題目鏈接:http://poj.org/problem?id=1177
            /*
            題意:
                給定N(N <= 5000)個矩形紙片,求它們重疊后外圍輪廓的周長。

            解法:
            線段樹

            思路:
                矩形面積并的變形,其實只需要修改Update函數即可,在線段樹的
            結點中保存一個nCover域,表示當前插入的線段覆蓋的次數,yCount表
            示當前y方向的長度的段數,LeftConnect和RightConnect表示當前結點
            的線段兩端點是否和父親結點的區間的左右端點連接,之后的工作就是
            在插入線段的時候隨即更新這些信息就可以了。
                然后統計周長的時候x方向和y方向都做一遍,其中一維線性枚舉,
            另一維通過線段樹區間插入,外輪廓的周長就是每次相鄰矩形統計的時
            候 線段樹根結點的段數*2*相鄰矩形邊的差 的總和。
                Update函數的更新如下:
                void Tree::Update() {
                if(nCover) {
                    // 當前區間的線段被完全覆蓋
                    yCount = 1;
                    LeftConnect = RightConnect = true;
                }else {
                    if(l + 1 == r) {
                        // 葉子結點的區間,并且未被覆蓋
                        yCount = 0;
                        LeftConnect = RightConnect = false;
                    }else {
                        // 內部結點所在區間,根據子樹的情況統計信息
                        LeftConnect = T[root<<1].LeftConnect;
                        RightConnect = T[root<<1|1].RightConnect;
                        yCount = T[root<<1].yCount + T[root<<1|1].yCount - 
                            ((T[root<<1|1].LeftConnect*T[root<<1].RightConnect)?1:0);
                    }
                }
            */


            #include 
            <iostream>
            #include 
            <vector>
            #include 
            <algorithm>
            using namespace std;

            #define maxn 20010

            struct VLine {
                
            int x;
                
            int y0, y1;
                
            int val;
                VLine() 
            {}
                VLine(
            int _x, int _y0, int _y1, int _val) {
                    x 
            = _x; 
                    y0 
            = _y0;
                    y1 
            = _y1;
                    val 
            = _val;
                }

            }
            ;
            vector 
            <VLine> Vl[2];

            bool cmp(VLine a, VLine b) {
                
            return a.x < b.x;
            }


            struct Tree {
                
            int root, l, r;
                
            int nCover;
                
            int ylen;
                
            int yCount;
                
            bool LeftConnect, RightConnect;

                
            void Update();
            }
            T[ maxn*4 ];

            void Tree::Update() {
                
            if(nCover) {
                    ylen 
            = r - l;
                    yCount 
            = 1;
                    LeftConnect 
            = RightConnect = true;
                }
            else {
                    
            if(l + 1 == r) {
                        ylen 
            = 0;
                        yCount 
            = 0;
                        LeftConnect 
            = RightConnect = false;
                    }
            else {
                        ylen 
            = T[root<<1].ylen + T[root<<1|1].ylen;
                        LeftConnect 
            = T[root<<1].LeftConnect;
                        RightConnect 
            = T[root<<1|1].RightConnect;
                        yCount 
            = T[root<<1].yCount + T[root<<1|1].yCount - 
                            ((T[root
            <<1|1].LeftConnect*T[root<<1].RightConnect)?1:0);
                    }

                }

            }



            void Build(int root, int l, int r) {
                T[root].l 
            = l;
                T[root].r 
            = r;
                T[root].root 
            = root;
                T[root].nCover 
            = T[root].ylen = T[root].yCount = 0;
                T[root].LeftConnect 
            = T[root].RightConnect = false;
                
            if(l + 1 == r) {
                    
            return ;
                }

                
            int mid = (l + r) >> 1;
                Build(root
            <<1, l, mid);
                Build(root
            <<1|1, mid, r);
            }


            void Insert(int root, int l, int r, int val) {
                
            if(T[root].l >= r || l >= T[root].r)
                    
            return ;

                
            if(l <= T[root].l && T[root].r <= r) {
                    T[root].nCover 
            += val;
                    T[root].Update();
                    
            return ;
                }


                Insert(root
            <<1, l, r, val);
                Insert(root
            <<1|1, l, r, val);

                T[root].Update();
            }


            int n;
            int main() {
                
            int i, j;
                
            while(scanf("%d"&n) != EOF) {
                    Vl[
            0].clear();
                    Vl[
            1].clear();
                    
            for(i = 0; i < n; i++{
                        
            int x0, y0, x1, y1;
                        scanf(
            "%d %d %d %d"&x0, &y0, &x1, &y1);
                        x0 
            += 10000; y0 += 10000;
                        x1 
            += 10000; y1 += 10000;
                        Vl[
            0].push_back( VLine(x0, y0, y1, 1) );
                        Vl[
            0].push_back( VLine(x1, y0, y1, -1) );

                        Vl[
            1].push_back( VLine(y0, x0, x1, 1) );
                        Vl[
            1].push_back( VLine(y1, x0, x1, -1) );
                    }
                
                    
            int ans = 0;

                    
            for(j = 0; j < 2; j++{
                        sort(Vl[j].begin(), Vl[j].end(), cmp);
                        Build(
            1020000);
                        
            for(i = 0; i < Vl[j].size(); i++{
                            
            if(i) {
                                ans 
            += 2 * (Vl[j][i].x - Vl[j][i-1].x) * T[1].yCount;
                            }

                            Insert(
            1, Vl[j][i].y0, Vl[j][i].y1, Vl[j][i].val);
                        }

                    }

                    printf(
            "%d\n", ans);
                }

                
            return 0;
            }

            posted on 2011-04-03 21:13 英雄哪里出來 閱讀(1365) 評論(0)  編輯 收藏 引用 所屬分類: 線段樹

            亚洲狠狠婷婷综合久久久久| 精品综合久久久久久97| 国内精品久久人妻互换| 久久se精品一区精品二区| 国产精品无码久久四虎| 欧美亚洲国产精品久久高清| 国产精品久久久久9999高清| 欧美久久久久久午夜精品| 久久婷婷国产综合精品| 亚洲成av人片不卡无码久久| 亚洲国产精品18久久久久久| 久久精品一区二区影院| 久久99精品久久久久婷婷| 久久久国产一区二区三区| 久久精品国产99久久无毒不卡| 久久免费观看视频| 久久免费线看线看| 久久九九精品99国产精品| 2021最新久久久视精品爱| 91麻豆精品国产91久久久久久| 精品免费久久久久久久| 青青草国产97免久久费观看| 91精品国产91热久久久久福利| 久久国产乱子伦免费精品| 久久亚洲精精品中文字幕| 久久久久亚洲AV无码专区首JN| 欧美性猛交xxxx免费看久久久| 久久播电影网| 国产精品99久久久久久猫咪| 精品国产乱码久久久久久郑州公司| 久久婷婷色香五月综合激情| 亚洲国产成人久久一区久久| 久久久久国产精品麻豆AR影院| 国产午夜精品久久久久九九| 久久精品国产一区| 久久精品国产影库免费看| 777米奇久久最新地址| 久久99热国产这有精品| 久久中文娱乐网| 久久WWW免费人成—看片| 欧美日韩成人精品久久久免费看|