• <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 英雄哪里出來 閱讀(1364) 評論(0)  編輯 收藏 引用 所屬分類: 線段樹

            久久综合九色综合97_久久久| 精品熟女少妇aⅴ免费久久| 欧美激情精品久久久久久久九九九| 国产亚洲美女精品久久久久狼| 国产精品久久久久9999| A级毛片无码久久精品免费| 四虎亚洲国产成人久久精品| 欧美一级久久久久久久大片| 久久精品亚洲AV久久久无码| 久久精品中文字幕无码绿巨人 | 66精品综合久久久久久久| 99久久99久久精品国产片| 久久久精品国产| 色综合合久久天天综合绕视看 | 亚洲国产婷婷香蕉久久久久久| 无码八A片人妻少妇久久| av无码久久久久不卡免费网站 | 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 91精品国产高清久久久久久91| 午夜精品久久久久久影视777| 久久久久青草线蕉综合超碰| 精品久久久久久综合日本| 国产69精品久久久久观看软件 | 国产成人无码精品久久久久免费| 亚洲精品综合久久| 青青草原综合久久| 久久久久亚洲AV成人片| 久久久这里有精品| 久久久国产精品| 99久久综合狠狠综合久久| 国产∨亚洲V天堂无码久久久| 久久香综合精品久久伊人| 久久国产免费| 久久精品国产一区二区三区不卡 | 国产精品乱码久久久久久软件| 国内精品久久国产大陆| 久久婷婷五月综合色奶水99啪| 久久综合久久伊人| 久久最新免费视频| 久久精品中文字幕有码| 久久强奷乱码老熟女网站|