• 洛谷P3299 保护出题人


    注意每一关的时候,前一关的植物会消失。保留整数指四舍五入。

    解:冷静分析一波,列一个式子出来,发现每一关的植物攻击力要是(ai + ... + aj) / (xi + d * (i - j))的最大值。1 <= j <= i

    然后把这个东西写成前缀和,分母的i和j分离:(si - sj-1) / (xi + d * i - d * j))

    发现就是两个点(xi + d * i, si)和(d * j, sj-1)之间的斜率。

    于是维护一个下凸包然后凸包上三分就行了。注意到插入的点的横坐标单增,单调栈即可。

    整数三分,就考虑l + 1 = r的时候怎么取,也比较好写。

     1 #include <bits/stdc++.h>
     2 
     3 typedef long long LL;
     4 const int N = 100010;
     5 const double eps = 1e-12;
     6 
     7 struct Vec {
     8     double x, y;
     9     Vec(double X = 0, double Y = 0) {
    10         x = X;
    11         y = Y;
    12     }
    13     inline Vec operator + (const Vec &w) const {
    14         return Vec(x + w.x, y + w.y);
    15     }
    16     inline Vec operator - (const Vec &w) const {
    17         return Vec(x - w.x, y - w.y);
    18     }
    19     inline double operator * (const Vec &w) const {
    20         return x * w.y - y * w.x;
    21     }
    22 };
    23 typedef Vec Poi;
    24 
    25 Poi node[N];
    26 LL a[N], x[N], sum[N], d;
    27 int n, top, stk[N];
    28 
    29 int main() {
    30     scanf("%d%lld", &n, &d);
    31     for(int i = 1; i <= n; i++) {
    32         scanf("%lld%lld", &a[i], &x[i]);
    33         sum[i] = sum[i - 1] + a[i];
    34     }
    35     double ans = 0;
    36     for(int i = 1; i <= n; i++) {
    37         Poi now(x[i] + i * d, sum[i]);
    38         node[i] = Poi(i * d, sum[i - 1]);
    39         while(top > 1 && (node[stk[top]] - node[stk[top - 1]]) * (node[i] - node[stk[top]]) < eps) {
    40             top--;
    41         }
    42         stk[++top] = i;
    43         //printf("stk %d = %d (%lld %lld) 
    ", top, i, i * d, sum[i - 1]);
    44         //printf("now (%lld %lld) 
    ", x[i] + i * d, sum[i]);
    45         int l = 1, r = top;
    46         while(l < r) {
    47             int mid = (l + r) >> 1;
    48             int ml = stk[mid], mr = stk[mid + 1];
    49             double vl = (double)(sum[i] - sum[ml - 1]) / (x[i] + (i - ml) * d),
    50                    vr = (double)(sum[i] - sum[mr - 1]) / (x[i] + d * (i - mr));
    51             //printf("vl = %lf vr = %lf 
    ", vl, vr);
    52             //printf("x = %lld y = %lld = %lld + %d * %lld 
    ", sum[i], x[i] + i * d, x[i], i, d);
    53             if(vl < vr) {
    54                 l = mid + 1;
    55             }
    56             else {
    57                 r = mid;
    58             }
    59         }
    60         ans += (double)(sum[i] - sum[stk[r] - 1]) / (x[i] + (i - stk[r]) * d);
    61         //printf("ans += %lf 
    ", (double)(sum[i] - sum[stk[r] - 1]) / (x[i] + (i - stk[r]) * d));
    62         //printf("r = %d 
    ", r);
    63         /*for(int j = 1; j <= top; j++) {
    64             printf("%d ", stk[j]);
    65         }
    66         puts("");*/
    67     }
    68 
    69     printf("%.0f
    ", ans);
    70     return 0;
    71 }
    AC代码
  • 相关阅读:
    2020系统综合实践 第3次实践作业
    2020系统综合实践 第2次实践作业
    2020系统综合实践 第1次实践作业
    WireShark组 2019 SDN大作业
    2019 SDN阅读作业
    第07组 Beta版本演示
    OO第四单元总结
    OO第三单元总结
    OO第二单元总结
    OO第一单元总结
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10823953.html
Copyright © 2020-2023  润新知