[BZOJ2216][Poi2011]Lightning Conductor[决策单调性优化]

最初在HDU的ACM模板上看到这个分治的DP优化

用这个的前提是不强制在线(f[i]不由前面的f转移过来)且决策单调

\[ \forall j\in \left[ \text{1,}n \right] \,\,p_i\ge a\left[ j \right] -a\left[ i \right] -\sqrt{|i-j|} \]
\[ p_i\ge \max ( a\left[ j \right] -a\left[ i \right] -\sqrt{|i-j|} ) \]
\[ p_i\ge \max \left( \max \left( a\left[ j \right] -a\left[ i \right] -\sqrt{i-j} \right) ,\max \left( a\left[ j \right] -a\left[ i \right] -\sqrt{j-i} \right) \right) \]

第15行和第7行 >=不能写成> 因为决策点单调,即使两个点的dp值相同,也要更新决策点

int a[MAXN * 5], n;
int dp1[MAXN * 5], dp2[MAXN * 5];

inline void DP1(int l, int r, int dl, int dr) {
  if (l > r) return ;
  int Max = 0; lf mx = 0;
  lop(i, dl, min(dr, mid)) if (a[i] - a[mid] + sqrt(mid - i) >= mx) Max = i, mx = a[i] - a[mid] + sqrt(mid - i);
  chmax(dp1[mid], a[Max] - a[mid] + ceil(sqrt(mid - Max)));
  DP1(l, mid - 1, dl, Max), DP1(mid + 1, r, Max, dr);
}

inline void DP2(int l, int r, int dl, int dr) {
  if (l > r) return ;
  int Max = 0; lf mx = 0;
  dlop(i, dr, max(dl, mid)) if (a[i] - a[mid] + sqrt(i - mid) >= mx) Max = i, mx = a[i] - a[mid] + sqrt(i - mid);
  chmax(dp2[mid], a[Max] - a[mid] + ceil(sqrt(Max - mid)));
  chmax(dp2[mid], dp1[mid]);
  DP2(l, mid - 1, dl, Max), DP2(mid + 1, r, Max, dr);
}

int main() {
#ifdef LOCAL_DEBUG
  // freopen("data.in", "r", stdin), freopen("data.out", "w", stdout);
  Dbg = 1; uint tim1 = clock();
#endif
  in, n;
  lop(i, 1, n) in, a[i];
  DP1(1, n, 1, n);
  DP2(1, n, 1, n);
  lop(i, 1, n) out, dp2[i], '\n';
#ifdef LOCAL_DEBUG
  fprintf(stderr, "\ntime:%.5lfms", (clock() - tim1) / (1.0 * CLOCKS_PER_SEC) * 1000);
#endif
  return 0;
}

转载于:https://www.cnblogs.com/storz/p/10190826.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值