洛谷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) \n", top, i, i * d, sum[i - 1]);
44         //printf("now (%lld %lld) \n", 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 \n", vl, vr);
52             //printf("x = %lld y = %lld = %lld + %d * %lld \n", 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 \n", (double)(sum[i] - sum[stk[r] - 1]) / (x[i] + (i - stk[r]) * d));
62         //printf("r = %d \n", r);
63         /*for(int j = 1; j <= top; j++) {
64             printf("%d ", stk[j]);
65         }
66         puts("");*/
67     }
68 
69     printf("%.0f\n", ans);
70     return 0;
71 }
AC代码

 

posted @ 2019-05-07 10:36  huyufeifei  阅读(146)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜