• <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 英雄哪里出來 閱讀(2013) 評論(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| 国产亚洲美女精品久久久| 欧美亚洲国产精品久久| 久久99久久99精品免视看动漫| A级毛片无码久久精品免费| 久久精品国产亚洲AV高清热| 国产免费福利体检区久久| 久久99久久无码毛片一区二区| 久久亚洲AV无码精品色午夜麻豆| 欧美精品久久久久久久自慰| 91久久精品电影| 久久久久久亚洲AV无码专区| 久久国产成人亚洲精品影院| 性欧美丰满熟妇XXXX性久久久| 精品熟女少妇aⅴ免费久久| 午夜人妻久久久久久久久| 久久久99精品一区二区| 久久久久久亚洲Av无码精品专口| 色综合合久久天天给综看| 精品综合久久久久久97超人| 成人久久免费网站| 蜜臀久久99精品久久久久久| 久久精品国产亚洲一区二区| 亚洲AV无码久久精品成人 | 国产精品亚洲综合久久| 久久久久一区二区三区| 亚洲AV无码一区东京热久久| 亚洲国产日韩综合久久精品| 久久精品国产精品亚洲人人| 999久久久免费国产精品播放| 久久夜色精品国产噜噜麻豆 | 无码人妻久久久一区二区三区 | 性欧美大战久久久久久久| 色综合久久中文色婷婷| 精品国产一区二区三区久久| 色88久久久久高潮综合影院| 中文字幕人妻色偷偷久久| 一个色综合久久| 97久久国产综合精品女不卡| 亚洲AV无码久久| 久久伊人精品青青草原高清|