zoukankan      html  css  js  c++  java
  • Codeforces 631E 斜率优化

    题意:给你一个数组,你可以选择数组中的一个数,把它插入数组的其它位置,问∑ i * a[i]的最大值为多少?

    思路:设dp[i]表示把第i个数向左边插入可以获得的最大增量,我们假设向左边插入,设插入的位置是j,当前位置是i,那么变化为sum[i - 1] - sum[j - 1] - (i - j) * a[i], 将式子转化,sum[j - 1] = a[i] * j - dp[i] + sum[i - 1] - i * a[i],我们要让dp[i]最大,即让-dp[i]最小,用单调队列维护下凸壳,查询的时候二分斜率即可。向右边插入同理。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 200010;
    LL q[maxn], l, r;
    LL a[maxn], sum[maxn];
    LL dp[maxn];
    int binary_search(LL k) {
    	if(r == l) return q[l];
    	int L = l, R = r;
    	while(L < R) {
    		int mid = (L + R) >> 1;
    		int tmp = q[mid], tmp1 = q[mid + 1];
    		if(sum[tmp1 - 1] - sum[tmp - 1] <= k * (tmp1 - tmp)) L = mid + 1;
    		else R = mid; 
    	}
    	return q[L];
    }
    int binary_search1(LL k) {
    	if(r == l) return q[l];
    	int L = l, R = r;
    	while(L < R) {
    		int mid = (L + R) >> 1;
    		int tmp = q[mid], tmp1 = q[mid + 1];
    		if(sum[tmp1] - sum[tmp] <= k * (tmp1 - tmp)) L = mid + 1;
    		else R = mid; 
    	}
    	return q[L];
    }
    int main() {
    	int n;
    	LL res = 0;
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld", &a[i]);
    		sum[i] = sum[i - 1] + a[i];
    		res = res + a[i] * i;
    	}
    	l = 1, r = 1, q[l] = 1, dp[1] = 0;
    	for (LL i = 2; i <= n; i++) {
    		int pos = binary_search(a[i]);
    		dp[i] = sum[i - 1] - sum[pos - 1] - (i - pos) * a[i];
    		while(l < r && (sum[q[r] - 1] - sum[q[r - 1] - 1]) * (i - q[r - 1]) >= (sum[i - 1] - sum[q[r - 1] - 1]) * (q[r] - q[r - 1]))r--;
    		q[++r] = i;
    	}
    	LL ans = -5e18;
    	for (int i = 1; i <= n; i++)
    		ans = max(ans, res + dp[i]);
    	l = 1, r = 1, q[1] = n;
    	dp[n] = 0; 
    	for (LL i = n - 1; i >= 1; i--) {
    		int pos = binary_search1(a[i]);
    		dp[i] = sum[i] - sum[pos] - (i - pos) * a[i];
    		while(l < r && (sum[q[r - 1]] - sum[i]) * (q[r] - i) <= (sum[q[r]] - sum[i]) * (q[r - 1] - i))r--;
    		q[++r] = i;
    	}
    	for (int i = 1; i <= n; i++)
    		ans = max(ans, res + dp[i]);
    	ans = max(ans, res);
    	printf("%lld
    ", ans);
    } 
    

      

  • 相关阅读:
    C#开发BIMFACE系列44 服务端API之计算图纸对比差异项来源自哪个图框
    C#开发BIMFACE系列43 服务端API之图纸拆分
    C#开发BIMFACE系列42 服务端API之图纸对比
    利用 OpenVINO 进行推理加速(一)
    虚拟化技术概述(一)
    利用目标跟踪来提高实时人脸识别处理速度
    目标追踪(Object Tracking)概念的简要介绍
    Python3 使用IMAP接收邮件
    Git使用
    Git基础
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10881326.html
Copyright © 2011-2022 走看看