zoukankan      html  css  js  c++  java
  • [HNOI2008]玩具装箱

    OJ题号:
      BZOJ1010

    思路:
      斜率优化动态规划。
      由题意得状态转移方程为$f_i=displaystyle{min_{j=0}^{i-1}}{f_j+left(i-j-1+displaystyle{sum_{k=j+1}^i}c_k-L ight)^2}$。
      用$a_i$表示$c_i$的前缀和,则原式为$f_i=displaystyle{min_{j=0}^{i-1}}{f_j+left(i-j-1+a_i-a_j-L ight)^2}$。
      考虑现在有两个状态$j$和$k$都可以转移到$i$。
      假设$j$比$k$更优,则有:$f_j+left(i-j-1+a_i-a_j-L ight)^2<f_k+left(i-k-1+=a_i-a_k-L ight)^2$。
      将与$i$有关的项提取出来,设$x=i-1+a_i-L$。
      则原式变为$f_j+left(x-j-a_j ight)^2<f_k+left(x-k-a_k ight)^2$。
      化简得$f_j+left(j+a_j ight)^2-f_k-left(k+a_k ight)^2<2x(j+a_j-k-a_k)$。
      即$frac{f_j+left(j+a_j ight)^2-f_k-left(k+a_k ight)^2}{(j+a_j-k-a_k)}<2x$。
      对于状态$j<k<l$,若要使$k$为一个有用的状态,则有$frac{f_k+(k+a_k)^2-f_j-(j+a_j)^2}{2(k+a_k-j-a_j)}<xleqfrac{f_l+(l+a_l)^2-f_k-(k+a_k)^2}{2(l+a_l-k-a_k)}$。
      然后我们可以维护一个单调队列,使队列中的相邻元素的斜率单调递增。
      每当插入一个元素时,我们比较队列前端两个元素的斜率是否小于$x$,如果是,则将第一个元素弹出队列。
      这时候队列前端的元素一定是最优的一个状态。
      然后尝试将这个元素加入队列,为了保证队列中相邻元素之间的斜率单调递增,每次比较队列后端两个元素的斜率$x1$和队列最末端元素与当前元素$i$的斜率$x2$。
      如果$x1>x2$,即新加入元素后不满足单调性,则将队列末端元素弹出。
      由于每个元素最多只会进队一次,最后的时间复杂度是$O(n)$的。

     1 #include<cstdio>
     2 #include<cctype>
     3 inline int getint() {
     4     register char ch;
     5     while(!isdigit(ch=getchar()));
     6     register int x=ch^'0';
     7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     8     return x;
     9 }
    10 const int N=50001;
    11 int n,l,a[N]={0},q[N]={0},h=0,t=0;
    12 long long f[N]={0};
    13 inline long long sqr(const long long x) {
    14     return x*x;
    15 }
    16 inline double slope(const int &j,const int &k) {
    17     return double(f[j]+sqr(j+a[j])-f[k]-sqr(k+a[k]))/double(j+a[j]-k-a[k]);
    18 }
    19 inline bool check(const int &i,const int &j,const int &k) {
    20     return slope(k,j)>2*(i+a[i]-l-1);
    21 }
    22 inline bool check2(const int &i,const int &j,const int &k) {
    23     return slope(j,i)<slope(k,j);
    24 }
    25 int main() {
    26     n=getint(),l=getint();
    27     for(register int i=1;i<=n;i++) {
    28         a[i]=a[i-1]+getint();
    29         while(h<t&&!check(i,q[h],q[h+1])) h++;
    30         const int &j=q[h];
    31         f[i]=f[j]+sqr(i-j-1+a[i]-a[j]-l);
    32         while(h<t&&!check2(q[t-1],q[t],i)) t--;
    33         q[++t]=i;
    34     }
    35     printf("%lld
    ",f[n]);
    36     return 0;
    37 }
  • 相关阅读:
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
    Data Structure and Algorithm
  • 原文地址:https://www.cnblogs.com/skylee03/p/7591426.html
Copyright © 2011-2022 走看看