• <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 2892 Tunnel Warfare

            題目鏈接:http://poj.org/problem?id=2892
            /*
            題意:
                給出M(M <= 50000)組操作,每組操作的形式如下:
            1 D x: 將第x個村莊摧毀
            2 Q x: 詢問和第x個村莊直接或者間接連接的村莊數目
            3 R: 修復上一個被摧毀的村莊

            解法:
            線段樹 或者 樹狀數組

            思路:
                線段樹染色問題,和ZJU 2301 Color the Ball類似,也是尋找最長連
            續區間。但是這題要簡單的多,因為插入的時候是對點操作,不需要用到
            lazy標記,線段樹中可以保存如下信息:

                enum eKind {
                    EK_BLACK = 0,
                    EK_WHITE = 1,
                };

                int root, l, r;   
                int lMax;          // 包含左區間的連續空閑區間的最大值
                int rMax;          // 包含右區間的連續空閑區間的最大值
                int mMax;          // 當前結點管轄區間的最大值

                首先來看下問題對應的操作,題目中有兩種插入,一個是插入一個摧毀
            的村莊,另一個是插入一個修復的村莊,其實原理是一樣的。只不過這兩種
            類型更新lMax,rMax,mMax的時候稍有不同,每次插入到線段樹元區間時,
            根據插入的eKind類型填充mMax、lMax、rMax的信息,否則更新他們的結點
            信息,然后遞歸左右兒子,繼續插入操作,遞歸返回時我們用以下函數從左
            右兒子中得到當前結點的信息:
            void UpdateBy(Tree* ls, Tree* rs);
            之所以把它寫成函數是因為這里的處理比較麻煩,很容易出錯,并且需要
            調用多次,這個函數的作用就是通過左右兒子的信息填充本身的信息。
            信息一多,處理的時候就要極為小心,因為很容易出錯。
            lMax表示當前結點的包含左閉區間的最優解。
            rMax表示當前結點的包含右閉區間的最優解。
            mMax則是當前區間的最優解。
            這樣我們就可以通過傳遞性在兒子結點的屬性都得知的情況下將父親的值
            計算出來,最后遞歸到根結點。具體的計算過程可以自己畫棵樹看一下,
                然后是查詢操作,查詢的話首先來看遞歸出口,我們用兩個引用來表示
            當前查到的信息是否左連通以及是否右連通,那么如果到元區間的時候當前
            點的mMax是0,那么直接左右連通標記都標記為false,否則為true。如果不
            是元區間,則判斷當前點在左兒子還是右兒子,如果在左兒子,那么遞歸左
            右子,回歸時根據返回的引用值判斷當前是否右連通,如果右連通,那么將
            右兒子的lMax值加到答案上來,再判斷lMax是否等于右兒子的len,如果不
            相等說明下次回歸上去的時候必然不是右連通,標記置為false,對于右兒子
            的情況做相同處理即可。回歸到根結點就是最后的答案了。
                這題還可以用樹狀數組來做,寫起來也比較方便,還是利用成段求和來
            統計當前點區間內的K大值,K值用二分枚舉即可。
            */

            #include 
            <iostream>

            using namespace std;

            #define maxn 50010

            enum eKind {
                EK_BLACK 
            = 0,
                EK_WHITE 
            = 1,
            }
            ;

            struct Tree {
                
            int root, l, r;
                
            int lMax, rMax, mMax;

                
            void CoverBy(eKind ek);
                
            void UpdateBy(Tree* ls, Tree* rs);

                
            int len() {
                    
            return r - l + 1;
                }

            }
            T[4*maxn];

            void Build(int p, int l, int r) {
                T[p].root 
            = p;
                T[p].l 
            = l;
                T[p].r 
            = r;
                T[p].rMax 
            = T[p].lMax = T[p].mMax = T[p].len();
                
            if(l == r)
                    
            return ;
                
            int mid = (l + r) >> 1;
                Build(p
            <<1, l, mid);
                Build(p
            <<1|1, mid+1, r);
            }


            int MMax(int a, int b) {
                
            return a > b ? a : b;
            }


            int MMax(int a, int b, int c, int d) {
                
            return MMax( MMax(a, b), MMax(c, d) );
            }


            void Tree::UpdateBy(Tree* ls, Tree* rs) {
                lMax 
            = ls->lMax; if(lMax == ls->len()) lMax += rs->lMax;
                rMax 
            = rs->rMax; if(rMax == rs->len()) rMax += ls->rMax;
                mMax 
            = MMax(lMax, rMax);
                mMax 
            = MMax(mMax, ls->mMax, rs->mMax, ls->rMax + rs->lMax);
            }


            void Tree::CoverBy(eKind ek) {
                mMax 
            = lMax = rMax = (ek==EK_WHITE) ? len() : 0;
            }


            void Insert(int p, int pos, eKind ek) {
                
            if(pos > T[p].r || pos < T[p].l)
                    
            return ;
                
            if(T[p].l == pos && pos == T[p].r) {
                    T[p].CoverBy(ek);
                    
            return ;
                }

                Insert(p
            <<1, pos, ek);
                Insert(p
            <<1|1, pos, ek);

                T[p].UpdateBy(
            &T[p<<1], &T[p<<1|1]);
            }


            int Query(int p, int pos, bool& lc, bool& rc) {
                
            if(T[p].l == pos && pos == T[p].r) {
                    lc 
            = rc = T[p].mMax;
                    
            return T[p].mMax;
                }


                
            int x;
                
            if(pos <= T[p<<1].r) {
                    x 
            = Query(p<<1, pos, lc, rc);
                    
            if(rc) {
                        x 
            += T[p<<1|1].lMax;
                        
            if(T[p<<1|1].lMax < T[p<<1|1].len())
                            rc 
            = false;
                    }

                }
            else {
                    x 
            = Query(p<<1|1, pos, lc, rc);
                    
            if(lc) {
                        x 
            += T[p<<1].rMax;
                        
            if(T[p<<1].rMax < T[p<<1].len())
                            lc 
            = false;
                    }

                }

                
            return x;
            }


            int n, m;
            int stack[maxn], top;
            int main() {
                
            char str[5];
                
            int x;
                
            while(scanf("%d %d"&n, &m) != EOF) {
                    Build(
            11, n);
                    top 
            = 0;
                    
            while(m--{
                        scanf(
            "%s", str);
                        
            if(str[0== 'D'{
                            scanf(
            "%d"&stack[top]);
                            Insert(
            1, stack[top], EK_BLACK);
                            top 
            ++;
                        }
            else if(str[0== 'R'{
                            
            if(top) {
                                top 
            --;
                                Insert(
            1, stack[top], EK_WHITE);
                            }

                        }
            else {
                            scanf(
            "%d"&x);
                            
            // 左連通、右連通
                            bool lc, rc;
                            printf(
            "%d\n", Query(1, x, lc, rc));
                        }

                    }

                }

                
            return 0;
            }

            posted on 2011-04-07 12:31 英雄哪里出來 閱讀(1476) 評論(0)  編輯 收藏 引用 所屬分類: 線段樹樹狀數組

            精品久久久无码21p发布| 伊人久久大香线蕉av不卡 | 久久综合九色欧美综合狠狠| 久久久久免费视频| 99久久久精品| 久久婷婷五月综合成人D啪| 亚洲综合精品香蕉久久网| 久久精品国产只有精品2020| 久久人人爽人人爽人人片AV东京热| 亚洲va久久久噜噜噜久久男同| 色婷婷久久久SWAG精品| 久久久久国产一区二区| 色欲av伊人久久大香线蕉影院| 国产成人精品久久一区二区三区av| 午夜精品久久久久久毛片| 99久久国产综合精品网成人影院| 色综合久久88色综合天天| 国产精品免费看久久久| 久久久久久久97| 国产精品久久久久无码av| 久久人人爽人人爽人人片AV麻豆| 久久综合精品国产二区无码| 国产香蕉久久精品综合网| 久久久久久久精品妇女99 | 伊人久久大香线蕉AV一区二区 | 久久这里只有精品18| 久久精品国产第一区二区| 久久青青草原精品国产| 伊人久久大香线蕉综合Av| 久久亚洲国产精品成人AV秋霞| 久久国产成人午夜aⅴ影院| 久久久WWW成人免费毛片| 久久综合九色综合久99| 97久久精品无码一区二区天美| 欧美黑人激情性久久| 久久精品国产亚洲AV香蕉| 久久99精品久久久久婷婷| 久久99精品久久只有精品 | 久久e热在这里只有国产中文精品99| 久久99中文字幕久久| 91性高湖久久久久|