题意:给出一个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;
}