• <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>

            PKU3017

            Posted on 2011-07-08 12:40 Mato_No1 閱讀(500) 評論(1)  編輯 收藏 引用 所屬分類: 平衡樹動態規劃
            【原題見這里

            本沙茶見過的最猥瑣的DP題啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊……

            設F[i]為將A[1..i]拆分成若干段的最大值最小和,則有
            F[i]=min{F[j] + max[j+1, i]}(B[i]<=j<i),其中max[j+1, i]表示A[j+1..i]中的最大值,B[i]表示從i向左最遠可以延伸到哪里(也就是滿足SUM[x..i]<=m的最小的x值)。B數組可以通過預處理在O(N)時間內得到。
            邊界:F[0]=0。

            下面是優化過程。JZP神犇的論文里面已經夠詳細了。這里只是簡要說明一下。
            首先容易證明,F是單調遞增的。
            然后一個很關鍵的定理是:若F[i]的最優決策為j,則有A[j]>∀A[k](j<k<=i)。
            證明:用反證法。若A[j+1..i]中存在不小于A[j]的值,則可得max[j..i]=max[j+1..i],又因為F單調遞增,所以F[j-1]+max[j..i]<=F[j]+max[j+1.i],即決策(j-1)一定不比決策j差,也就是決策j不可能成為最優決策。
            這樣,可以維護一個下標嚴格遞增、A值嚴格遞減的隊列Q(即對于隊列中的任意兩個元素Q[i]和Q[j],若i<j,則Q[i].pos<Q[j].pos且A[Q[i].pos]>A[Q[j].pos],具體實現時pos可省略)。則可能成為最優決策的決策要么是在這個隊列Q里,要么是B[i]。對于隊列中的某個決策Q[x],該決策導出的值為F[Q[x]]+A[Q[x + 1]](很容易證明max[Q[x]+1..i]=A[Q[x + 1]]),找到這些導出的值中的最小值即可(注意,隊尾元素沒有導出值)。對于決策B[i],只需要在預處理的時候同時得到MAX[i]=max[B[i]+1..i]即可(也可以在O(N)時間內得到),決策B[i]導出的值為F[B[i]]+MAX[i]。
            在刪除隊首過時元素的時候,需要把導出值也刪除,刪除隊尾元素也一樣,插入的時候,若插入前隊列不為空,則需要插入一個導出值。也就是,需要一個支持在對數時間內進行插入、刪除任意結點、找最小值等操作,顯然用平衡樹最好。

            注意事項:
            (1)不管是在隊首刪除還是在隊尾刪除,若刪除的是隊列中的最后一個元素,則不需要在平衡樹中刪除導出值;
            (2)插入時,若插入前隊列為空,則不需要在平衡樹中插入導出值;
            (3)在計算F[i]時,應先將決策i壓入。

            代碼:
            #include <iostream>
            #include 
            <stdio.h>
            using namespace std;
            #define re1(i, n) for (int i=1; i<=n; i++)
            const int MAXN = 100001;
            struct node {
                
            int l, r, p, sz0, sz, mul;
                
            long long v;
            } T[MAXN];
            const long long INF = ~0Ull >> 2;
            int n, N = 0, a[MAXN], b[MAXN], MAX[MAXN], Q[MAXN], front = 0, rear = -1, root = 0;
            long long m, F[MAXN], res = 0;
            void init()
            {
                cin 
            >> n >> m;
                re1(i, n) scanf(
            "%d"&a[i]); a[0= ~0U >> 2;
            }
            void prepare()
            {
                re1(i, n) 
            if (a[i] > m) {res = -1return;}
                
            int x = 1;
                
            long long sum = 0;
                re1(i, n) {
                    
            for (sum+=a[i]; sum>m; sum-=a[x++]) ;
                    b[i] 
            = x - 1;
                }
                re1(i, n) {
                    
            for (; front<=rear && Q[front]<=b[i]; front++) ;
                    
            for (; front<=rear && a[Q[rear]]<=a[i]; rear--) ;
                    Q[
            ++rear] = i; MAX[i] = a[Q[front]];
                }
            }
            void vst(int x)
            {
                
            if (x) {
                    cout 
            << T[x].v << ' ';
                    vst(T[x].l); vst(T[x].r);
                }
            }
            void slc(int _p, int _c)
            {
                T[_p].l 
            = _c; T[_c].p = _p;
            }
            void src(int _p, int _c)
            {
                T[_p].r 
            = _c; T[_c].p = _p;
            }
            void upd(int x)
            {
                T[x].sz0 
            = T[T[x].l].sz0 + T[T[x].r].sz0 + T[x].mul;
                T[x].sz 
            = T[T[x].l].sz + T[T[x].r].sz + 1;
            }
            void lrot(int x)
            {
                
            int y = T[x].p;
                
            if (y == root) T[root = x].p = 0else {int p = T[y].p; if (y == T[p].l) slc(p, x); else src(p, x);}
                src(y, T[x].l); slc(x, y); T[x].sz0 
            = T[y].sz0; T[x].sz = T[y].sz; upd(y);
            }
            void rrot(int x)
            {
                
            int y = T[x].p;
                
            if (y == root) T[root = x].p = 0else {int p = T[y].p; if (y == T[p].l) slc(p, x); else src(p, x);}
                slc(y, T[x].r); src(x, y); T[x].sz0 
            = T[y].sz0; T[x].sz = T[y].sz; upd(y);
            }
            void maintain(int x, bool ff)
            {
                
            int z;
                
            if (ff) {
                    
            if (T[T[T[x].r].r].sz > T[T[x].l].sz) {z = T[x].r; lrot(z);}
                    
            else if (T[T[T[x].r].l].sz > T[T[x].l].sz) {z = T[T[x].r].l; rrot(z); lrot(z);} else return;
                } 
            else {
                    
            if (T[T[T[x].l].l].sz > T[T[x].r].sz) {z = T[x].l; rrot(z);}
                    
            else if (T[T[T[x].l].r].sz > T[T[x].r].sz) {z = T[T[x].l].r; lrot(z); rrot(z);} else return;
                }
                maintain(T[z].l, 
            0); maintain(T[z].r, 1); maintain(z, 0); maintain(z, 1);
            }
            int find(long long _v)
            {
                
            int i = root;
                
            long long v0;
                
            while (i) {
                    v0 
            = T[i].v;
                    
            if (_v == v0) return i; else if (_v < v0) i = T[i].l; else i = T[i].r;
                }
                
            return 0;
            }
            int Find_Kth(int K)
            {
                
            int i = root, s0, m0;
                
            while (1) {
                    s0 
            = T[T[i].l].sz0; m0 = T[i].mul;
                    
            if (K <= s0) i = T[i].l; else if (K <= s0 + m0) return i; else {K -= s0 + m0; i = T[i].r;}
                }
            }
            void ins(long long _v)
            {
                
            if (!root) {
                    T[
            ++N].v = _v; T[N].l = T[N].r = T[N].p = 0; T[N].sz0 = T[N].sz = T[N].mul = 1; root = N;
                } 
            else {
                    
            int i = root, j;
                    
            long long v0;
                    
            while (1) {
                        T[i].sz0
            ++; v0 = T[i].v;
                        
            if (_v == v0) {T[i].mul++return;} else if (_v < v0) j = T[i].l; else j = T[i].r;
                        
            if (j) i = j; else break;
                    }
                    T[
            ++N].v = _v; T[N].l = T[N].r = 0; T[N].sz0 = T[N].sz = T[N].mul = 1if (_v < v0) slc(i, N); else src(i, N);
                    
            while (i) {T[i].sz++; maintain(i, _v > T[i].v); i = T[i].p;}
                }
            }
            void del(int x)
            {
                
            if (T[x].mul > 1) {
                    T[x].mul
            --while (x) {T[x].sz0--; x = T[x].p;}
                } 
            else {
                    
            int l = T[x].l, r = T[x].r, p;
                    
            if (l && r) {
                        
            int y; while (y = T[l].r) l = y;
                        T[x].v 
            = T[l].v; T[x].mul = T[l].mul; p = T[l].p;
                        
            if (l == T[p].l) slc(p, T[l].l); else src(p, T[l].l);
                        
            while (p) {upd(p); p = T[p].p;}
                    } 
            else {
                        
            if (x == root) T[root = l + r].p = 0else {p = T[x].p; if (x == T[p].l) slc(p, l + r); else src(p, l + r); while(p) {upd(p); p = T[p].p;}}
                    }
                }
            }
            long long h(int x)
            {
                
            return F[Q[x]] + a[Q[x + 1]];
            }
            void solve()
            {
                F[
            0= 0; front = 0; rear = 0; Q[0= 0;
                re1(i, n) {
                    
            for (; front<=rear && Q[front]<b[i];) {if (front < rear) del(find(h(front))); front++;}
                    
            for (; front<=rear && a[Q[rear]]<=a[i];) {if (front < rear) del(find(h(rear - 1))); rear--;}
                    Q[
            ++rear] = i; if (front < rear) ins(h(rear - 1));
                    
            if (root) F[i] = T[Find_Kth(1)].v; else F[i] = INF;
                    
            if (F[b[i]] + MAX[i] < F[i]) F[i] = F[b[i]] + MAX[i];
                }
                res 
            = F[n];
            }
            void pri()
            {
                cout 
            << res << endl;
            }
            int main()
            {
                init();
                prepare();
                
            if (!res) solve();
                pri();
                
            return 0;
            }

            Feedback

            # re: PKU3017  回復  更多評論   

            2012-05-15 10:05 by olyminfo
            求 JZP神犇的論文 出處。。。
            国产99精品久久| 国产精品丝袜久久久久久不卡| 久久无码AV中文出轨人妻| 一本久久精品一区二区| 国产精品美女久久久m| 久久久久国产一区二区| 中文字幕无码精品亚洲资源网久久| 久久婷婷成人综合色综合| 91精品国产91久久久久久| 亚洲AV日韩精品久久久久久| 久久久久久久尹人综合网亚洲| 中文成人无码精品久久久不卡| 久久精品aⅴ无码中文字字幕重口| 久久93精品国产91久久综合| 国产毛片欧美毛片久久久| 久久久久国色AV免费看图片| 久久久女人与动物群交毛片| 伊人久久大香线蕉成人| 久久久九九有精品国产| 色欲av伊人久久大香线蕉影院| 久久99国产精品二区不卡| 亚洲欧美日韩久久精品第一区| 久久免费香蕉视频| 91麻豆精品国产91久久久久久| 久久精品国产亚洲AV大全| 久久亚洲AV成人无码软件| 亚州日韩精品专区久久久| 四虎国产精品免费久久5151| 久久精品国产亚洲AV无码偷窥| 久久这里的只有是精品23| 久久影院亚洲一区| 亚洲精品无码久久毛片| 久久国产精品波多野结衣AV| 91精品日韩人妻无码久久不卡 | 奇米影视7777久久精品| 久久久不卡国产精品一区二区 | 久久www免费人成看片| 青青草原综合久久大伊人导航| 久久青青草原亚洲av无码| 久久国产香蕉视频| 久久人人青草97香蕉|