洛谷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 }