Description
题解
模拟费用流体验题??
先口胡一个思想,大概就是我们需要做的就是模拟费用流的贪心/退流思想
我们分别开一个小根堆维护外卖员与商店的反悔策略
那么分别讨论
首先按x值排序
当我们插入一个外卖员的时候,我们从商店的堆中拿出一个权值
这样其实就相当于让他强行与左边的商店匹配了
我们知道外卖员一定有可能反悔的,所以我们扔进外卖员的堆中一个 − ( x + c ) − x -(x+c)-x −(x+c)−x的权,其中 c c c表示从商店堆中拿出的权值
那么再考虑插入商店的时候怎么办
相似的,我们强行让他先与左边的外卖员匹配。
那么从外卖员的堆中拿出一个权值 c c c,如果 c + x + w c+x+w c+x+w是小于 0 0 0的话那么显然左边有至少一个外卖员换成这个商店是更优秀的
同理,这时候商店和外卖员都是可能反悔的
商店的反悔,在于他可能匹配右边的外卖员,那么往商店堆中扔一个 − ( c + x + w ) − x + w -(c+x+w)-x+w −(c+x+w)−x+w的权
外卖员的反悔,在于他可能匹配更右边的商店,那么往外卖员堆中扔一个 − x − w -x-w −x−w的权,取出后相当于把这次操作撤销了
我们发现一个商店可能被匹配多次,那么每次相同的权值我们就记录一个有多少数量扔进堆里面
很吼的思想啊!!!
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(LL x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const int MAXN=200005;
priority_queue<pll,vector<pll>,greater<pll> > hp1,hp2;
LL ans=0;
void insman(int x)
{
pll temp=hp2.top();hp2.pop();
ans+=temp.first+x;
if(temp.second>1)hp2.push(mp(temp.first,temp.second-1));
hp1.push(mp(-(x+temp.first)-x,1));
}
void insroom(int x,int w,int c)
{
int now=0;
while(hp1.size()&&hp1.top().first+x+w<0&&now<c)
{
pll temp=hp1.top();hp1.pop();
int tot=min(temp.second,(LL)c-now);
ans+=(x+w+temp.first)*tot;
now+=tot;
hp2.push(mp(-(x+w+temp.first)-x+w,tot));
tot=temp.second-tot;
if(tot)hp1.push(mp(temp.first,tot));
}
if(now<c)hp2.push(mp(-x+w,c-now));
if(now)hp1.push(mp(-x-w,now));
}
int n,m;
struct node
{
int x,w,c,opt;
}w[MAXN];int ln;
bool cmp(node n1,node n2){return n1.x!=n2.x?n1.x<n2.x:n1.opt>n2.opt;}
int main()
{
// freopen("ex_hole2.in","r",stdin);
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();m=read();
LL sum=0;
for(int i=1;i<=n;i++)w[++ln].x=read(),w[ln].opt=1;
for(int i=1;i<=m;i++)
{
w[++ln].x=read();w[ln].w=read();w[ln].c=read();
w[ln].opt=2;sum+=w[ln].c;
}
if(sum<n)return puts("-1"),0;
sort(w+1,w+1+ln,cmp);
hp2.push(mp((1LL<<31-1),(1LL<<31-1)));
for(int i=1;i<=n+m;i++)
{
if(w[i].opt==1)insman(w[i].x);
else insroom(w[i].x,w[i].w,w[i].c);
}
pr2(ans);
return 0;
}