• <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, 評(píng)論 - 81, 引用 - 0
            數(shù)據(jù)加載中……

            HDU 3308 LCIS

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

            /*
            題意:
                給出一個(gè)長(zhǎng)度為N(N <= 100000)的數(shù)列,然后是兩種操作:
            U A B: 將第A個(gè)數(shù)替換為B (下標(biāo)從零開(kāi)始)
            Q A B: 輸出區(qū)間[A, B]的最長(zhǎng)連續(xù)遞增子序列
            注意:操作的數(shù)目m <= 100000。

            解法:
            線段樹(shù)

            思路:
                做慣了區(qū)間最值、求和、修改、染色的等問(wèn)題,這題算比較新穎
            的了,由這題可以看出線段樹(shù)的一般解法,因?yàn)檫@題要求保存的信息
            比較多,每個(gè)線段樹(shù)的結(jié)點(diǎn)要求保存的信息有以下幾個(gè):

                int lMax;       // 包含結(jié)點(diǎn)左端點(diǎn)的最長(zhǎng)連續(xù)遞增子序列的長(zhǎng)度
                int rMax;       // 包含結(jié)點(diǎn)右端點(diǎn)的最長(zhǎng)連續(xù)遞增子序列的長(zhǎng)度
                int Max;        // 當(dāng)前結(jié)點(diǎn)的最長(zhǎng)連續(xù)遞增子序列的長(zhǎng)度
                int lVal, rVal; // 當(dāng)前結(jié)點(diǎn)管轄的區(qū)間左右端點(diǎn)的數(shù)值
                int l, r;       // 當(dāng)前結(jié)點(diǎn)管轄的區(qū)間

            我們用以下函數(shù)從左右兒子中得到當(dāng)前結(jié)點(diǎn)的信息:
            void UpdateBy(Tree* ls, Tree* rs);
            之所以把它寫(xiě)成函數(shù)是因?yàn)檫@里的處理比較麻煩,很容易出錯(cuò),并且需要
            調(diào)用多次,這個(gè)函數(shù)的作用就是通過(guò)左右兒子的信息填充本身的信息。

            lVal、rVal、l、r等信息比較容易求得。
            lMax和rMax的值就比較麻煩了,需要分情況討論(下面的len表示區(qū)間長(zhǎng)度):
            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);

            一開(kāi)始讀入的時(shí)候有一連串?dāng)?shù)字,需要建樹(shù),建樹(shù)的時(shí)候每次回歸時(shí)需要
            將兒子的信息傳遞給父親,調(diào)用UpdateBy(Tree* ls, Tree* rs)函數(shù),每
            次插入完畢后回歸時(shí),信息會(huì)更新,也需要調(diào)用。詢問(wèn)時(shí),返回的也是一
            個(gè)線段樹(shù)結(jié)點(diǎn),并且需要將答案合并,還是需要調(diào)用UpdateBy函數(shù),所以
            總的來(lái)說(shuō)需要調(diào)用三次,把它寫(xiě)成一個(gè)函數(shù)還是勢(shì)在必行的。
            */



            #include 
            <iostream>

            using namespace std;

            #define maxn 100010

            struct Tree {
                
            int lMax;       // 包含結(jié)點(diǎn)左端點(diǎn)的最長(zhǎng)連續(xù)遞增子序列
                int rMax;       // 包含結(jié)點(diǎn)右端點(diǎn)的最長(zhǎng)連續(xù)遞增子序列
                int Max;        // 當(dāng)前結(jié)點(diǎn)的最長(zhǎng)連續(xù)遞增子序列
                int lVal, rVal; // 當(dāng)前區(qū)間左右端點(diǎn)的值
                int l, r;       // 當(dāng)前結(jié)點(diǎn)管轄的區(qū)間
                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 英雄哪里出來(lái) 閱讀(2021) 評(píng)論(2)  編輯 收藏 引用 所屬分類(lèi): 線段樹(shù)

            評(píng)論

            # re: HDU 3308 LCIS  回復(fù)  更多評(píng)論   

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

            # re: HDU 3308 LCIS  回復(fù)  更多評(píng)論   

            新生,敢問(wèn),為什么這樣區(qū)分是對(duì)的呢??
            還是沒(méi)有想明白,請(qǐng)大神解析一下。
            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
            久久婷婷五月综合成人D啪| 99久久国产综合精品五月天喷水| 伊人久久大香线焦综合四虎| 99久久国产热无码精品免费| 国产精品激情综合久久| 一97日本道伊人久久综合影院| 亚洲精品无码成人片久久| 狠狠色丁香久久婷婷综| 合区精品久久久中文字幕一区 | 伊人色综合久久天天人守人婷| 蜜臀久久99精品久久久久久| 亚洲国产另类久久久精品| 嫩草影院久久99| 亚洲午夜久久久久久久久久| 亚洲综合精品香蕉久久网97| 人妻无码精品久久亚瑟影视| 久久精品国产免费| 久久狠狠爱亚洲综合影院| 99久久国产免费福利| 免费精品国产日韩热久久| 国产亚洲成人久久| 国产精品美女久久久久久2018| 欧美精品福利视频一区二区三区久久久精品 | 一级做a爰片久久毛片看看| 俺来也俺去啦久久综合网| 久久久久久久波多野结衣高潮| 国产高清美女一级a毛片久久w| 久久久久亚洲av无码专区导航| 精品久久久久久无码人妻蜜桃| 久久A级毛片免费观看| 热99RE久久精品这里都是精品免费 | 久久精品中文字幕一区| 久久久久无码专区亚洲av| 久久久久久夜精品精品免费啦| 狠狠色丁香婷婷久久综合五月| 久久久久噜噜噜亚洲熟女综合| 精品人妻伦九区久久AAA片69| 嫩草影院久久99| 久久精品女人天堂AV麻| 国产福利电影一区二区三区久久老子无码午夜伦不 | 色偷偷偷久久伊人大杳蕉|