zoukankan      html  css  js  c++  java
  • “景驰科技杯”2018年华南理工大学程序设计竞赛 G. Youhane as "Bang Riot"(斜率DP)

    题目链接:https://www.nowcoder.com/acm/contest/94/G

    题意:中文题目,见链接

    题解:设 sum[i] 为 a[i] 的前缀和,可得公式

    dp[i] = min( dp[j] + ( sum[i] - sum[j] -  b[i] ) ^ 2 )

              = min( dp[j] + sum[j] ^ 2 + 2 * ( sum[i] - b[i] ) * ( sum[i] - sum[j] ) + sum[i] - b[i] ) ^ 2 

    设 y = dp[j] + sum[j] ^ 2,k = sum[i] - b[i],x = sum[i] - sum[j],b = sum[i] - b[i] ) ^ 2

    有 y = 2 * k * x + b

    因为 k 的正负不确定,但 y 和 x 符合单调性,故可以二分找出第一个比当前点斜率大的点来维护下凸性(注意最好手写二分,使用lower_bound可能会出错)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 1e6 + 10;
    13 const int MAXM = 1e3 + 10;
    14 const ll mod = 100000073;
    15  
    16 int n,tail;
    17 int q[MAXN];
    18 ll a[MAXN],b[MAXN],sum[MAXN],dp[MAXN];
    19 double k[MAXN];
    20  
    21 ll sqr(ll x) {
    22     return x * x;
    23 }
    24  
    25 ll getup(int j,int k) {
    26     return dp[j] + sqr(sum[j]) - (dp[k] + sqr(sum[k]));
    27 }
    28  
    29 ll getdown(int j,int k) {
    30     return 2ll * (sum[j] - sum[k]);
    31 }
    32  
    33 int findd(double x) {
    34     int l = 0, r = tail - 1, ans = 0;
    35     while(l <= r) {
    36         int mid = (l + r) >> 1;
    37         ll up = dp[q[mid]] + sqr(sum[q[mid]]) - (dp[q[mid - 1]] + sqr(sum[q[mid - 1]]));
    38         ll down = 2.0 * (sum[q[mid]] - sum[q[mid - 1]]);
    39         if(up <= down * x) l = mid + 1, ans = mid;
    40         else r = mid - 1;
    41     }
    42     return q[ans];
    43 }
    44  
    45 int main() {
    46 #ifdef local
    47     freopen("data.txt", "r", stdin);
    48 #endif
    49     sum[0] = dp[0] = 0;
    50     while(~scanf("%d",&n)) {
    51         for(int i = 1; i <= n; i++) {
    52             scanf("%lld",&a[i]);
    53             sum[i] = sum[i - 1] + a[i];
    54         }
    55         for(int i = 1; i <= n; i++) scanf("%lld",&b[i]);
    56         tail = 0;
    57         q[tail++] = 0;
    58         for(int i = 1; i <= n; i++) {
    59             int id = findd(1.0 * (sum[i] - b[i]));
    60             dp[i] = dp[id] + sqr(sum[i] - sum[id] - b[i]);
    61             while(1 < tail && getup(q[tail - 1],q[tail - 2]) * getdown(i,q[tail - 1]) >= getup(i,q[tail - 1]) * getdown(q[tail - 1],q[tail - 2]))
    62                 tail--;
    63             if(getdown(i,q[tail - 1]) == 0) k[tail] = 1e18;
    64             else k[tail] = 1.0 * getup(i,q[tail - 1]) / getdown(i,q[tail - 1]);
    65             q[tail++] = i;
    66         }
    67         printf("%lld
    ",dp[n]);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    86. Partition List
    2. Add Two Numbers
    55. Jump Game
    70. Climbing Stairs
    53. Maximum Subarray
    64. Minimum Path Sum
    122. Best Time to Buy and Sell Stock II
    以场景为中心的产品设计方法
    那些产品经理犯过最大的错
    Axure教程:如何使用动态面板?动态面板功能详解
  • 原文地址:https://www.cnblogs.com/scaulok/p/9770065.html
Copyright © 2011-2022 走看看