题解「LOJ2348 「JOI 2018 Final」美术展览」
转载注明来源:https://www.cnblogs.com/syc233/p/13803903.html
题意
有 \(n\) 个物品,物品 \(i\) 有尺寸 \(A_i\) 和价值 \(B_i\) 。选择若干个物品,使得选择的物品的总价值 \(S\) 减尺寸的极差 \(A_{max}-A_{min}\) 最大。
题解
发现若固定 \(A_{min}\) 和 \(A_{max}\) ,那么一定将尺寸在 \([A_{min},A_{max}]\) 中的物品选完,那么 \(S\) 的值就很好求得。将物品按 \(A\) 升序排序,那么选择的物品一定是一段区间。
同时固定两个值有些困难,先固定一个值 \(A_{min}\)。令 \(A_{min}\) 在排好序的物品中下标为 \(i\) , \(A_{max}\) 的下标为 \(j\) ,有 \(i\leq j\) 。则需要最大化的值即为:
\[\sum_{k=i}^jB_k-(A_j-A_i)
\]
令 \(sum\) 表示 \(B\) 的前缀和,则有:
\[sum_j-sum_{i-1}-(A_j-A_i)=sum_j-A_j-(sum_{i-1}-A_i)
\]
从右到左枚举 \(i\) ,记录 \(sum_j-A_j,j\in [i,n]\) 的最大值,依次更新答案即可。
\(\text{Code}:\)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <climits>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=5e5+5;
template <typename T>
inline void read(T &x)
{
x=0;T f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
x*=f;
}
struct Art
{
lxl A,B;
Art(lxl A,lxl B):A(A),B(B){}
Art(){}
inline bool operator < (const Art &T)const
{
return A<T.A;
}
}art[maxn];
int n;
lxl sum[maxn];
int main()
{
// freopen("#2348.in","r",stdin);
read(n);
for(int i=1;i<=n;++i)
read(art[i].A),read(art[i].B);
sort(art+1,art+n+1);
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+art[i].B;
lxl ans=LLONG_MIN,Max=LLONG_MIN;
for(int i=n;i>=1;--i)
{
Max=max(Max,sum[i]-art[i].A);
ans=max(ans,Max-sum[i-1]+art[i].A);
}
printf("%lld\n",ans);
return 0;
}