P9025 [CCC2021 S3] Lunch Concert 题解
思路
把一个人转化成一个线段
于是我们就能得到一个分段函数。
利用离散化和差分把所有的分段函数加起来,取个最小值。
注:最小值一定在某个端点处取到。
code
#include<stdio.h>
#include<algorithm>
#define N 444444
using namespace std;
inline char nc()
{
static char buf[99999],*l,*r;
return l==r&&(r=(l=buf)+fread(buf,1,99999,stdin),l==r)?EOF:*l++;
}
inline void read(int&x)
{
char c=nc();for(;c<'0'||'9'<c;c=nc());
for(x=0;'0'<=c&&c<='9';x=(x<<3)+(x<<1)+(c^48),c=nc());
}
int n,m,lsh[N],p[N],w[N],d[N];long long a[N],b[N],ans;
inline void add(const int&l,const int&r,const int&x,const long long&y)
{a[l]+=x;a[r+1]-=x;b[l]+=y;b[r+1]-=y;}
inline void min(long long&x,const long long&y){if(x>y)x=y;}
main()
{
read(n);
for(int i=0;i<n;++i)
{
read(p[i]);read(w[i]);read(d[i]);
lsh[m++]=p[i]-d[i];
lsh[m++]=p[i]+d[i];
}
sort(lsh,lsh+m);m=unique(lsh,lsh+m)-lsh;
for(int i=0,x;i<n;++i)
{
x=p[i]-d[i];
add(0,lower_bound(lsh,lsh+m,x)-lsh,-w[i],(long long)(w[i])*x);
x=p[i]+d[i];
add(upper_bound(lsh,lsh+m,x)-lsh,m,w[i],-(long long)(w[i])*x);
}
ans=a[0]*lsh[0]+b[0];
for(int i=1;i<=m;++i)
{
a[i]+=a[i-1];b[i]+=b[i-1];
if(a[i]>>63)min(ans,a[i]*lsh[i]+b[i]);
else min(ans,a[i]*lsh[i-1]+b[i]);
}
printf("%lld",ans);
}