hdu 3507 斜率优化
我的第一道斜率优化。
就这道题而言,写出原始的方程:
dp[i] = min{ dp[j] + (sum[i]-sum[j])2 + M | j in [0,i) }
O(n^2)的复杂度肯定超时,要么优化转移,要么重写方程。
斜率优化的思想就是减少不必要的枚举(即不枚举肯定不会成为决策点的j)。
我们考虑两个位置p<q<i
“选择q比选择p优” 当且仅当 dp[q]+(sum[i]-sum[q])2+M < dp[p]+(sum[i]-sum[p])2+M
化简右边即:
[ (dp[q]+sum2[q])-(dp[p]+sum2[p]) ] / ( sum[q]-sum[p] ) < sum[i]*2
该式可以看成两个点连线的斜率:( sum[q], dp[q]+sum2[q] ) 与 ( sum[p], dp[p]+sum2[p] ) 两点。
文字语言就是:“将每个决策位置看成一个二维坐标系下的点,对于两个决策点,后者比前者优 当且仅当 两点连线的斜率小于sum[i]*2”
这样怎么减少不必要的枚举呢?
可以发现,所有决策点一定是单调不下降的(题中可能出现权值为0,此时有可能出现斜率为正无穷,若M=0,还有可能出现重点,所以计算斜率不要用除法)
上面的B点一定是不会成为最优决策点的,反证法:
如果B成为最优决策点,那么
2*sum[i]>kab 且 2*sum[i]<kbc
而显然kab > kbc ,这样就推出了2*sum[i]>kab >kbc >2*sum[i],矛盾。
故B不可能成为最优决策点,同理,D也不行,删掉这些点后,我们剩下的图形就是一个下凸的图形了:
我们维护这样一个下凸的图形到队列中:
当要查找i位置的最优决策点时,一直删除队首的点,直到队中的第一条直线的斜率大于2*sum[i]或队中只有一个点,此时队首元素就是最优决策点。
计算完i位置后,要将i位置对应的点加入到队列中,此时会删除一些对尾的点,以保持队中点的下凸性(注意处理重合的点)。
这样,我们就利用斜率优化掉了很多不必要的枚举,将时间复杂度从O(n^2)降到了O(n)。
1 #include <cstdio> 2 #define ln(A,B) ((B)-(A)) 3 #define maxn 500010 4 5 typedef long long lng; 6 7 struct Vector { 8 lng x, y; 9 int id; 10 Vector(){} 11 Vector( lng x, lng y, int id ) : x(x), y(y), id(id) {} 12 Vector operator-( const Vector & b ) const { return Vector(x-b.x,y-b.y,0); } 13 lng operator&( const Vector & b ) const { 14 return x*b.y-y*b.x; 15 } 16 }; 17 typedef Vector Point; 18 19 int n, m; 20 int cost[maxn]; 21 lng sum[maxn]; 22 lng dp[maxn]; 23 24 int beg, end; 25 Point qu[maxn]; 26 27 int main() { 28 while( 1 ) { 29 if( scanf( "%d%d", &n, &m )!=2 ) return 0; 30 31 sum[0] = 0; 32 for( int i=1; i<=n; i++ ) { 33 scanf( "%d", cost+i ); 34 sum[i] = sum[i-1]+cost[i]; 35 } 36 37 dp[0] = 0; 38 qu[beg=end=0] = Point( 0, 0, 0 ); 39 40 for( int i=1; i<=n; i++ ) { 41 while( end>beg && qu[beg+1].y-qu[beg].y<=(qu[beg+1].x-qu[beg].x)*2*sum[i] ) 42 beg++; 43 int j = qu[beg].id; 44 dp[i] = dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+m; 45 Point npt = Point( sum[i], dp[i]+sum[i]*sum[i], i ); 46 while( end>beg && (ln(qu[end-1],qu[end])&ln(qu[end-1],npt))<=0 ) 47 end--; 48 qu[++end] = npt; 49 } 50 printf( "%lld\n", dp[n] ); 51 } 52 }