bzoj 1010 玩具装箱toy -斜率优化

  P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压
缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1...N的N件玩具,第i件玩具经过
压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容
器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一
个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,
如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容
器,甚至超过L。但他希望费用最小.


Input

  第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7


Output

  输出最小费用


Sample Input

5 4
3
4
2
1
4

Sample Output

1


  先推出普通dp的方程    f[i] = min{f[j] + (sum[i] - sum[j] + i - j - 1 - L)2}

  这方程明显是O(n2)级别的,再看看这卖萌的数据范围,不用质疑,铁定超时。还是来考虑一下优化(例如斜率优化)吧。由于这方程长得太丑了,于是决定简化一下

  设S(i) = sum[i] + i,C = L + 1

  于是方程变成了这样    f[i] = min{f[j] + (S(i) - S(j) - C)2}

  现在假设在状态i之前有两个可以转移到i的两个状态j, k(j < k),现在使j比k更优,那么它要满足

f[j] + (S(i) - S(j) - C)2 < f[k] + (S(i) - S(k) - C)2

  看平方不爽,而且无法化简,果断完全平方公式拆掉

f[j] + [S(i) - (S(j) + C)]2 < f[k] + [S(i) - (S(k) + C)]2

f[j] + (S(j) + C)2 - 2S(i)[S(j) + C] < f[j] + (S(k) + C)2 - 2S(i)[S(k) + C]

  (其实可以一起拆掉,只不过中途有些地方可以直接"抵消")继续"拆"括号,移项

f[j] + S(j)2 + 2S(j)C - 2S(i)[S(j) - S(k)] < f[k] + S(k)2 + 2S(k)C

  继续,右边只留一个和i有关的单项式

(f[j] + S(j)2 + 2S(j)C) - (f[k] + S(k)2 + 2S(k)C) < 2S(i)[S(j) - S(k)]

  继续移项,右边只留和i有关的式子

  注意,S(i)是单调递增,所以S(j) - S(k) < 0,移项的时候不等号方向相反,于是我们愉快地得到了斜率方程(干什么?斜率优化去掉一个n)。

  对于点i,用(f[i] + S(i)2 + 2S(i)C)作纵坐标,2S(i)作横坐标。

Code

  1 /**
  2  * uva
  3  * Problem#1451
  4  * Accepted
  5  * Time:60ms
  6  */
  7 #include<iostream>
  8 #include<sstream>
  9 #include<cstdio>
 10 #include<cmath>
 11 #include<cstdlib>
 12 #include<cstring>
 13 #include<cctype>
 14 #include<queue>
 15 #include<set>
 16 #include<map>
 17 #include<stack>
 18 #include<vector>
 19 #include<algorithm>
 20 using namespace std;
 21 typedef bool boolean;
 22 #define smin(a, b) (a) = min((a), (b))
 23 #define smax(a, b) (a) = max((a), (b))
 24 template<typename T>
 25 inline void readInteger(T& u){
 26     char x;
 27     int aFlag = 1;
 28     while(!isdigit((x = getchar())) && x != ‘-‘);
 29     if(x == ‘-‘){
 30         aFlag = -1;
 31         x = getchar();
 32     }
 33     for(u = x - ‘0‘; isdigit((x = getchar())); u = u * 10 + x - ‘0‘);
 34     ungetc(x, stdin);
 35     u *= aFlag;
 36 }
 37
 38 template<typename T>
 39 class IndexedDeque{
 40     public:
 41         T* list;
 42         int pfront;
 43         int prear;
 44         IndexedDeque():list(NULL), pfront(0), prear(0){        }
 45         IndexedDeque(int size):pfront(0), prear(0){
 46             list = new T[size];
 47         }
 48         void push_front(T x){    list[--pfront] = x;        }
 49         void push_back(T x)    {    list[prear++] = x;        }
 50         void pop_front()    {    ++pfront;                }
 51         void pop_back()        {    --prear;                }
 52         T     front()        {    return list[pfront];    }
 53         T     rear()            {    return list[prear - 1];        }
 54         T& operator [](int pos){            return list[pfront + pos];        }
 55         int size()            {    return prear - pfront;    }
 56 };
 57
 58 int T;
 59 int n, L;
 60 int* sum;
 61 char* str;
 62 IndexedDeque<int> que;
 63
 64 inline int segsum(int from, int end){    return sum[end] - sum[from - 1];    }
 65 inline int cmpSlope(int l1, int r1, int l2, int r2){    return (segsum(l1, r1) * (r2 - l2 + 1)) - (segsum(l2, r2) * (r1 - l1 + 1)); }
 66
 67 inline void init(){
 68     readInteger(n);
 69     readInteger(L);
 70     str = new char[(const int)(n + 1)];
 71     sum = new int[(const int)(n + 1)];
 72     que = IndexedDeque<int>(n * 2);
 73     scanf("%s", str);
 74 }
 75
 76 inline void solve(){
 77     sum[0] = 0;
 78     for(int i = 0; i < n; i++)
 79         sum[i + 1] = sum[i] + str[i] - ‘0‘;
 80
 81     int resl = 1, resr = L;
 82     for(int i = L; i <= n; i++){
 83         while(que.size() > 1 && cmpSlope(que[que.size() - 2], i - L, que[que.size() - 1], i - L) >= 0)
 84             que.pop_back();
 85         que.push_back(i - L + 1);
 86         while(que.size() > 1 && cmpSlope(que[0], i, que[1], i) <= 0)
 87             que.pop_front();
 88
 89         int temp = cmpSlope(que.front(), i, resl, resr);
 90         if(temp > 0 || (temp == 0 && resr - resl > i - que.front())){
 91             resl = que.front(), resr = i;
 92         }
 93     }
 94     printf("%d %d\n", resl, resr);
 95 }
 96
 97 inline void clear(){
 98     delete[] sum;
 99     delete[] str;
100     delete[] que.list;
101 }
102
103 int main(){
104     readInteger(T);
105     while(T--){
106         init();
107         solve();
108         clear();
109     }
110     return 0;
111 } 
时间: 2024-08-07 08:16:33

bzoj 1010 玩具装箱toy -斜率优化的相关文章

BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)

Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<

BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器

bzoj 1010 玩具装箱toy

摘自YYF的blog,斜率优化,敬一个! P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sig

[BZOJ1010] [HNOI2008] 玩具装箱toy (斜率优化)

Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<

HNOI2008玩具装箱 (斜率优化)

总算A了,心情好激动-- 如果会了一类斜率优化,基本上这类题就成了套模版了-- 只是k函数不同 1 var n,l,x,tail,head,m:int64; 2 i,j:longint; 3 dp,q,s:array[0..100000] of int64; 4 function k(x,y:longint):double; 5 begin 6 k:=1.0*((dp[x]+s[x]*s[x]-dp[y]-s[y]*s[y])/(s[x]-s[y])); 7 end; 8 procedure m

BZOJ 1010 玩具装箱 斜率优化DP

详情见 http://www.cnblogs.com/proverbs/archive/2013/02/01/2713109.html(我觉得这里面讲得已经够详细了,我就不赘述了) 还是来回忆一下做这道题的历程吧!一开始的确有点想错了,但马上又反应过来,清楚了题意.写了个 n^2 的算法.很明显,对于n <=  50000 的数据,肯定是要TLE的.(援引我看博客过程中看到的一句话来形容就是“省选题的数据就是硬”.)没办法,只能上网找百度(太弱了).一开始的确有点茫然,但马上就决定要自己推导一下

【斜率DP】BZOJ 1010:玩具装箱

1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7537  Solved: 2888[Submit][Status][Discuss] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P

P3195 [HNOI2008]玩具装箱TOY DP+优化

题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j

玩具装箱 bzoj1010 斜率优化

斜率优化的题好像都是这样的方程:左边关于j,k的一个(...)/(...)的式子,右边是个只与i有关的可算的数字: 然后把它放到二维坐标轴上,用单调队列维护一个凸壳,O(n)的复杂度: 这道题但是我发现我wrong了,找了程序看了一下,才发现斜率优化还有一点没理解:才明白上午T2能A是由于数据太水,出题人万岁! 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define LL long long