1 条题解

  • 0
    @ 2025-8-24 21:47:28

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar ModestCoder_
    这个家伙不懒,但还是什么也没有留下

    搬运于2025-08-24 21:47:28,当前版本为作者最后更新于2019-08-12 12:26:28,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这并不是一道dp

    对于每个ii,答案是ansi=max(sumisumj1xi+(ij)d)ans_i=max(\frac{sum_i-sum_{j-1}}{x_i+(i-j)d}) 其中sumi=j=1iajsum_i=\sum_{j=1}^{i}a_j

    可以斜率优化,因为答案的表达式可以看成(xi+id,sumi)(jd,sumj1)(x_i+i*d,sum_i)(j*d,sum_{j-1})两点的斜率

    发现对于每个ii,(xi+id,sumi)(x_i+i*d,sum_i)是个定点

    所以对于点(jd,sumj1)(j*d,sum_{j-1})维护一个下凸包,二分查找凸包中与定点相连斜率最大值

    把每一个ii的答案累加起来即可

    Code:

    #include <bits/stdc++.h>
    #define maxn 100010
    #define int long long
    using namespace std;
    struct data{
    	int x, y;
    }stk[maxn];
    int n, D, sum[maxn], top;
    double Ans;
    
    inline int read(){
    	int s = 0, w = 1;
    	char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
    	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
    	return s * w;
    }
    
    double slope(data x, data y){ return 1.0 * (x.y - y.y) / (x.x - y.x); }
    
    signed main(){
    	n = read(), D = read();
    	stk[0] = (data){0, 0};
    	for (int i = 1; i <= n; ++i){
    		int x = read(), y = read(); sum[i] = sum[i - 1] + x;
    		data tmp = {i * D, sum[i - 1]};
    		while (top && slope(stk[top - 1], stk[top]) > slope(stk[top], tmp)) --top;
    		stk[++top] = tmp;
    		tmp = (data){y + i * D, sum[i]};
    		int l = 1, r = top, ans = 0;
    		while (l <= r){
    			int mid = (l + r) >> 1;
    			if (slope(stk[mid], tmp) > slope(stk[mid - 1], tmp)) ans = mid, l = mid + 1; else r = mid - 1;
    		}
    		Ans += slope(stk[ans], tmp);
    	}
    	printf("%.0f\n", Ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    2372
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者