G. Vasya and Maximum Profit

传送门

题意:给出一个n,一个price,n道题,每道题都有一个难度值d【i】和需要支付的价格a【i】

还有一个gap(l,r)=maxl≤i<r(d(i+1)−d(i))2

放入一道题需要支付a【i】的钱。可以获得price的钱。一场比赛中的题目在区间【l,r】之间,再支付gap(l,r)的价格。

求最大值

分析:最终获得的价格可以由三部分组成,两部分是需要支出,一部分是收入。

收入是题目的数量乘以price;

支出1是每道题需要支付的价格a【i】;

支出2是最终确定的题目的区间(l,r);

首先收入部分可以以O(n)的求最大字段和算法。

支出1可以在输入的时候预处理一下,把权值处理一下。和收入部分一起用O(n)处理。

但是对于(l,r)的区间也需要进行预处理,如何进行操作?

对于每一个不同gap,我们都可以找出它的最大区间。

即 在 L1到R1的区间中,gap为d【1】;

即 在 L2到R2的区间中,gap为d【2】;

所以我们需要维护的是对于每一个d【i】找出属于它 的最大区间,在这个区间中进行最大子段求和;

/*#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;

#define sp system("pause");
#define N 300001
#define LL long long
LL n, price,l[N],r[N], a[N], d[N], ans;

LL getsum(LL l, LL r) {
	LL maxSum = 0, thisSum = 0;
	for (int j = l; j <= r; j++) {
		thisSum += a[j];
		if (maxSum < thisSum)
			maxSum = thisSum;
		else if (thisSum<0)
			thisSum = 0;
	}
	return maxSum;
}

int main()
{
	scanf("%lld%lld", &n, &price);
	for (LL i = 1; i <= n; i++)
	{
		scanf("%lld%lld", &d[i], &a[i]);
		a[i] = price - a[i]; ans = max(ans, a[i]);
	}
	for (LL i = n; i >= 1; i--)d[i] -= d[i - 1];
	d[1] = 0;
	l[2] = 2, r[n] = n;
	for (LL i = 3; i <= n; i++)
	{
		LL _ = i;
		while (_>2 && d[i] >= d[_ - 1])
			_ = l[_ - 1];
		l[i] = _;
	}
	for (LL i = n - 1; i >= 2; i--)
	{
		LL _ = i;
		while (_<n && d[i] >= d[_ + 1])
			_ = r[_ + 1];
		r[i] = _;
	}
	for (LL i = 2; i <= n; i++)
	{
		LL  res = getsum(l[i] - 1, r[i]);
		ans = max(ans, res - d[i] * d[i]);
	}
	printf("%lld\n", ans);
	return 0;
}*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
#define maxn 300100
#define sp system("pause");
#define LL long long
LL n, price,ans=0;
LL d[maxn], a[maxn],l[maxn],r[maxn];

LL getmax(LL l,LL r) {
	LL thismax = 0, totalmax = 0;
	for (LL i = l; i <= r; i++){
		thismax += a[i];
		if (thismax > totalmax)
			totalmax = thismax;
		if (thismax < 0)
			thismax = 0;
	}
	return totalmax;
}

int main() {
	scanf("%lld%lld", &n, &price);
	for (LL i = 1; i <= n; i++) {
		scanf("%lld%lld", &d[i], &a[i]);
		a[i] = price - a[i];
		ans = max(ans, a[i]);
	}
	d[0] = 0;
	for (LL i = n; i >= 1; i--)d[i] -= d[i - 1];
	l[2] = 2;
	for (LL i = 3; i <= n; i++) {
		LL t=i;
		while (t > 2 && d[i] >= d[t - 1])
			t = l[t - 1];
		l[i] = t;
	}
	r[n] = n;
	for (LL i = n-1; i >= 2; i--) {
		LL t = i;
		while (t < n && d[i] >= d[t + 1])
			t = r[t + 1];
		r[i] = t;
	}
	for (LL i = 2; i <= n; i++) {
		ans = max(ans, getmax(l[i] - 1, r[i])-d[i]*d[i]);
	}
	printf("%lld\n", ans);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41539869/article/details/86678467
今日推荐