zoukankan      html  css  js  c++  java
  • BZOJ3156 防御准备

    我去什么破题跳调了我一个半小时。

    不是裸的斜率优化吗。。。我去我去我去我去我去我去!

    首先我们倒着读进来,然后就省略了倒过来做的问题。

    然后写出DP方程:

    令f[i]表示选i作为塔时1到i的总代价,则

    f[i] = min(f[j] + w(i, j) + a[i])   其中有j < i 且 w(i, j) = (j - i - 1) * (j - i) / 2

    整理可得到f[i] = g[j] + cost[i] - i * j的形式,于是

    斜率优化即可。然后沙茶的我就开始了调程序之旅~~~我去。

     1 /**************************************************************
     2     Problem: 3156
     3     User: rausen
     4     Language: C++
     5     Result: Accepted
     6     Time:1532 ms
     7     Memory:28152 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <algorithm>
    12  
    13 using namespace std;
    14 typedef long long ll;
    15 const int N = 1000005;
    16 ll a[N], f[N], g[N], ans;
    17 int n, l, r, q[N];
    18  
    19 inline int read(){
    20     int x = 0;
    21     char ch = getchar();
    22     while (ch < '0' || ch > '9')
    23         ch = getchar();
    24     while (ch >= '0' && ch <= '9'){
    25         x = x * 10 + ch - '0';
    26         ch = getchar();
    27     }
    28     return x;
    29 }
    30  
    31 inline ll calc_f(ll i, ll x){
    32     return (ll) g[x] + a[i] - i * x * 2 + (i - 1) * i;
    33 }
    34  
    35 inline ll calc_g(ll x){
    36     return (ll) f[x] + x * (x + 1);
    37 }
    38  
    39 inline ll calc_ans(ll x){
    40     return (ll) f[x] + (n - x) * (n - x + 1);
    41 }
    42  
    43 bool pop_head(ll i){
    44     ll x = q[l], y = q[l + 1];
    45     return ((ll) i * (y - x) * 2 >= (ll) g[y] - g[x]);
    46 }
    47  
    48 bool pop_tail(ll i){
    49     ll x = q[r - 1], y = q[r];
    50     return ((ll) (g[i] - g[y]) * (y - x) < (ll) (g[y] - g[x]) * (i - y));
    51 }
    52  
    53 int main(){
    54     n = read();
    55     for (int i = n; i; --i)
    56         a[i] = read() << 1;
    57     f[1] = a[1], g[1] = calc_g(1), ans = calc_ans(1);
    58     q[1] = l = r = 1;
    59     for (int i = 2; i <= n; ++i){
    60         while (l < r && pop_head(i)) ++l;
    61         f[i] = calc_f(i, q[l]);
    62         g[i] = calc_g(i);
    63         ans = min(ans, calc_ans(i));
    64         while (l < r && pop_tail(i)) --r;
    65         q[++r] = i;
    66     }
    67     printf("%lld
    ", ans >> 1);
    68     return 0;
    69 }
    View Code

    (p.s.   rank3是我小号~~rank4是我自己,还是蛮快滴!Oh耶)

    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    Kafka写入流程和副本策略
    Kafka消费分组和分区分配策略
    Kafka安装和常用操作命令
    面试:谈谈你对大数据的理解
    HDFS写数据和读数据流程
    java笔记之分支、循环语句
    java笔记之分支、循环语句
    java笔记之运算符
    java笔记之运算符
    java笔记之java内存结构
  • 原文地址:https://www.cnblogs.com/rausen/p/4041467.html
Copyright © 2011-2022 走看看