• <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
            數據加載中……

            HDU 3308 LCIS

            題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3308

            /*
            題意:
                給出一個長度為N(N <= 100000)的數列,然后是兩種操作:
            U A B: 將第A個數替換為B (下標從零開始)
            Q A B: 輸出區間[A, B]的最長連續遞增子序列
            注意:操作的數目m <= 100000。

            解法:
            線段樹

            思路:
                做慣了區間最值、求和、修改、染色的等問題,這題算比較新穎
            的了,由這題可以看出線段樹的一般解法,因為這題要求保存的信息
            比較多,每個線段樹的結點要求保存的信息有以下幾個:

                int lMax;       // 包含結點左端點的最長連續遞增子序列的長度
                int rMax;       // 包含結點右端點的最長連續遞增子序列的長度
                int Max;        // 當前結點的最長連續遞增子序列的長度
                int lVal, rVal; // 當前結點管轄的區間左右端點的數值
                int l, r;       // 當前結點管轄的區間

            我們用以下函數從左右兒子中得到當前結點的信息:
            void UpdateBy(Tree* ls, Tree* rs);
            之所以把它寫成函數是因為這里的處理比較麻煩,很容易出錯,并且需要
            調用多次,這個函數的作用就是通過左右兒子的信息填充本身的信息。

            lVal、rVal、l、r等信息比較容易求得。
            lMax和rMax的值就比較麻煩了,需要分情況討論(下面的len表示區間長度):
            1. 左兒子最右邊的值 < 右兒子最左邊的值

                lMax = (左兒子的lMax == 左兒子的len) ? 左兒子的len + 右兒子的lMax : 左兒子的lMax;
                rMax = (右兒子的rMax == 右兒子的len) ? 右兒子的len + 左兒子的rMax : 右兒子的rMax;
                Max  = MAX(左兒子的rMax + 右兒子的lMax, 左兒子的Max, 右兒子的Max, lMax, rMax);

            2. 左兒子最右邊的值 >= 右兒子最左邊的值

                lMax = 左兒子的lMax;
                rMax = 右兒子的rMax;
                Max  = MAX(左兒子的Max, 右兒子的Max);

            一開始讀入的時候有一連串數字,需要建樹,建樹的時候每次回歸時需要
            將兒子的信息傳遞給父親,調用UpdateBy(Tree* ls, Tree* rs)函數,每
            次插入完畢后回歸時,信息會更新,也需要調用。詢問時,返回的也是一
            個線段樹結點,并且需要將答案合并,還是需要調用UpdateBy函數,所以
            總的來說需要調用三次,把它寫成一個函數還是勢在必行的。
            */



            #include 
            <iostream>

            using namespace std;

            #define maxn 100010

            struct Tree {
                
            int lMax;       // 包含結點左端點的最長連續遞增子序列
                int rMax;       // 包含結點右端點的最長連續遞增子序列
                int Max;        // 當前結點的最長連續遞增子序列
                int lVal, rVal; // 當前區間左右端點的值
                int l, r;       // 當前結點管轄的區間
                int son[2];

                
            void clear() {
                    son[
            0= son[1= -1;
                }

                
            void UpdateBy(Tree* ls, Tree* rs);
                
            void Unit(int nl, int nr, int nv);
                
            int len() {
                    
            return r - l + 1;
                }

            }
            T[maxn*4];
            int root, tot;
            int val[ maxn ];

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


            int MAX(int a, int b, int c) {
                
            return MAX(MAX(a, b), c);
            }


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


            void Tree::UpdateBy(Tree* ls, Tree* rs) {
                lVal 
            = ls->lVal;
                rVal 
            = rs->rVal;
                l    
            = ls->l;
                r    
            = rs->r;
                
            if(ls->rVal < rs->lVal) {
                    lMax 
            = (ls->lMax == ls->len()) ? ls->len() + rs->lMax : ls->lMax;
                    rMax 
            = (rs->rMax == rs->len()) ? rs->len() + ls->rMax : rs->rMax;
                    
                    Max  
            = MAX(ls->rMax + rs->lMax, ls->Max, rs->Max);
                    Max  
            = MAX(Max, lMax, rMax);

                }
            else {
                    lMax 
            = ls->lMax;
                    rMax 
            = rs->rMax;
                    Max  
            = MAX(ls->Max, rs->Max);
                }

            }


            void Tree::Unit(int nl, int nr, int nv) {
                lMax 
            = rMax = 1; Max = 1;
                lVal 
            = rVal = nv;
                l 
            = nl; r = nr;
            }


            int GetID(int& root) {
                
            if(root == -1{
                    root 
            = tot++;
                    T[root].clear();
                }

                
            return root;
            }


            void Build(int& root, int l, int r) {
                GetID(root);
                
            if(l == r) {
                    T[root].Unit(l, r, val[l]);
                    
            return ;
                }

                
            int mid = (l + r) >> 1;
                Build(T[root].son[
            0], l, mid);
                Build(T[root].son[
            1], mid+1, r);

                T[root].UpdateBy(
            &T[ T[root].son[0] ], &T[ T[root].son[1] ]);
            }


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

                Insert(T[root].son[
            0], nPos, val);
                Insert(T[root].son[
            1], nPos, val);

                T[root].UpdateBy(
            &T[ T[root].son[0] ], &T[ T[root].son[1] ]);
            }


            Tree Query(
            int root, int nl, int nr) {
                
            if(nl > T[root].r || nr < T[root].l) {
                    Tree tmp;
                    tmp.Max 
            = -1;
                    
            return tmp;
                }


                
            if(nl <= T[root].l && T[root].r <= nr) {
                    
            return T[root];
                }

                Tree A, B;
                A 
            = Query(T[root].son[0], nl, nr);
                B 
            = Query(T[root].son[1], nl, nr);
                
            if(A.Max == -1)
                    
            return B;
                
            else if(B.Max == -1)
                    
            return A;
                
            else {
                    Tree X;
                    X.UpdateBy(
            &A, &B);
                    
            return X;
                }

            }


            int n, m;
            int main() {
                
            int t, i;
                scanf(
            "%d"&t);

                
            while(t--{
                    scanf(
            "%d %d"&n, &m);
                    
            for(i = 1; i <= n; i++{
                        scanf(
            "%d"&val[i]);
                    }

                    tot 
            = 0;
                    root 
            = -1;
                    Build(root, 
            1, n);
                    
            while(m--{
                        
            char str[10];
                        
            int A, B;
                        scanf(
            "%s %d %d", str, &A, &B);
                        
            if(!strcmp(str, "U")) {
                            Insert(root, A
            +1, B);
                        }
            else {
                            Tree tmp 
            = Query(root, A+1, B+1);
                            printf(
            "%d\n", tmp.Max);
                        }

                    }

                }

                
            return 0;
            }

            posted on 2011-04-01 02:36 英雄哪里出來 閱讀(2014) 評論(2)  編輯 收藏 引用 所屬分類: 線段樹

            評論

            # re: HDU 3308 LCIS  回復  更多評論   

            受教了!狂膜拜!
            2011-08-15 10:36 | Now_I

            # re: HDU 3308 LCIS  回復  更多評論   

            新生,敢問,為什么這樣區分是對的呢??
            還是沒有想明白,請大神解析一下。
            1. 左兒子最右邊的值 < 右兒子最左邊的值

            lMax = (左兒子的lMax == 左兒子的len) ? 左兒子的len + 右兒子的lMax : 左兒子的lMax;
            rMax = (右兒子的rMax == 右兒子的len) ? 右兒子的len + 左兒子的rMax : 右兒子的rMax;
            Max = MAX(左兒子的rMax + 右兒子的lMax, 左兒子的Max, 右兒子的Max, lMax, rMax);

            謝謝了。
            2013-04-27 18:57 | ni hao
            久久精品国产99国产精品澳门| 久久久噜噜噜久久| 亚洲国产精品一区二区久久hs| 久久精品中文无码资源站| 色88久久久久高潮综合影院| 久久精品国产网红主播| 久久久久99精品成人片牛牛影视| 久久亚洲中文字幕精品一区| 99久久精品国产高清一区二区| 久久久人妻精品无码一区 | 91麻豆国产精品91久久久| 久久久久久久波多野结衣高潮 | 7777精品伊人久久久大香线蕉| 无码人妻精品一区二区三区久久| 久久精品www| 无码人妻久久一区二区三区| 久久精品国产黑森林| 精品久久久久久亚洲精品| 欧美激情精品久久久久久久九九九| 欧美黑人又粗又大久久久| 亚洲精品视频久久久| 久久91亚洲人成电影网站| 色欲久久久天天天综合网精品| 久久影院亚洲一区| 日韩精品国产自在久久现线拍| 人妻无码αv中文字幕久久琪琪布| 久久久久久亚洲精品不卡| 成人精品一区二区久久| 久久国产精品成人免费| 日日噜噜夜夜狠狠久久丁香五月| 欧美日韩精品久久久免费观看| 好属妞这里只有精品久久| 久久久久无码精品国产| 狠狠色婷婷久久一区二区| 亚洲性久久久影院| 亚洲日本久久久午夜精品| 久久亚洲欧洲国产综合| 久久综合久久伊人| 伊人久久五月天| 伊人久久大香线蕉av一区| 久久亚洲春色中文字幕久久久 |