• <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
            久久亚洲AV成人无码电影| 亚洲精品乱码久久久久久蜜桃| 亚洲精品美女久久久久99| 色欲综合久久躁天天躁蜜桃 | 久久久久亚洲精品无码网址| 久久久久久亚洲精品无码| 久久久无码精品亚洲日韩京东传媒 | 久久香蕉国产线看观看乱码| 人妻少妇精品久久| 丰满少妇人妻久久久久久 | 国产精品久久国产精麻豆99网站| 国産精品久久久久久久| 久久男人Av资源网站无码软件| 精品水蜜桃久久久久久久| 国产精品久久久久国产A级| 亚洲精品美女久久久久99小说 | 国产精品乱码久久久久久软件| 久久精品国产91久久麻豆自制| 亚洲精品无码成人片久久| 欧美久久天天综合香蕉伊| 中文字幕一区二区三区久久网站| 久久精品国产亚洲av麻豆蜜芽 | 国产午夜免费高清久久影院| 香蕉久久久久久狠狠色| 国产亚州精品女人久久久久久| 精品久久久久久综合日本| 东京热TOKYO综合久久精品| 久久久久久久波多野结衣高潮| 欧美大战日韩91综合一区婷婷久久青草| 精品久久777| 久久国产成人午夜aⅴ影院| 亚洲嫩草影院久久精品| 91久久精品视频| 国产福利电影一区二区三区,免费久久久久久久精 | 精品国产综合区久久久久久| 人人狠狠综合久久亚洲婷婷| 国产精品免费福利久久| 国产精品久久99| 国产精品热久久无码av| 国产三级精品久久| 一级做a爰片久久毛片毛片|