#455. 【UER #8】雪灾与外卖

题目

先按左边排,考虑一个人/店不是匹配左边的(主动)就是让右边的匹配他(被动)

定义 $v$ 为堆顶(小根堆),至于是人堆还是店堆按具体情况。

一个人匹配某家店

匹配左边: $x+v$,那么 $v=w-y$。这里显然是店堆。

匹配右边:反悔,$-(x+v)-x$ 插入人堆。具体为什么插入这个东西下面会提到。

店匹配人(也就是人匹配右边的店,假如花费大于0,那么一定不优于让人匹配左边)

匹配左边:$w+y+v$ 的形式,那么实际上就是要 $v=-x$ ,至于 $-(x+v)$ 是为了撤销匹配左边的贡献。

匹配右边:$-(w+y+v)-y+w$ 因为考虑人匹配左边的店是 $x+v$,那么撤销这次店的匹配就是 $-(w+y+v)$,实际上 $x+v=x-y+w$。

但假如是店2匹配店1所匹配的人呢? 即可能相邻2个店。我们考虑将店1当人看。

设 $y1,w1,y2,w2,v$

那么店1匹配的人就是 $w1+y1+v$,那假如让店2替代,还需要花费 $(w2+y2+v)-(w1+y1+v)=w1+y1-w2-y2$,对照下店匹配人的式子,$y+w+v$,则$v=-y2-w2$,即往人堆插入 $-y-w$ 即可。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
 
#define ll long long
 
using namespace std;
int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}
ll lrd() {
    ll f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}

const int N=(int)(1e5+5);
struct node {
    mutable ll v,tot;
    bool operator < (const node &x) const {
        return v>x.v;
    }
    bool operator > (const node &x) const {
        return v<x.v;
    }
};
#define min(X,Y) (X>Y?Y:X)
const ll inf=0x7fffffff;
priority_queue<node>q1,q2;
ll ans;
int X[N],Y[N],W[N],C[N],n,m;

void ins1(int id) {
    ll qwq=inf;
    if(!q2.empty()) {
        node x=q2.top();
        qwq=X[id]+q2.top().v; 
        if(!(--q2.top().tot)) q2.pop();
    }
    ans+=qwq; q1.push((node){-qwq-X[id],1});
}

void ins2(int id) {
    int tot=0; ll res=0;
    while(!q1.empty()&&tot<C[id]) {
        ll qwq=q1.top().v+W[id]+Y[id];
        if(qwq>=0) break;
        int cnt=min(q1.top().tot,C[id]-tot);
        ans+=qwq*cnt; tot+=cnt;
        q2.push((node){-qwq-Y[id]+W[id],cnt});
        if(!(q1.top().tot-=cnt)) q1.pop();
    }
    if(tot) q1.push((node){-Y[id]-W[id],tot});
    if(C[id]-tot) q2.push((node){-Y[id]+W[id],C[id]-tot});
}

int main() {
    n=rd(); m=rd(); ll qwq=0;
    for(int i=1;i<=n;i++) X[i]=rd();
    for(int i=1;i<=m;i++) Y[i]=rd(),W[i]=rd(),C[i]=rd(),qwq+=C[i];
    if(qwq<n) {
        puts("-1"); return 0;
    }
    int j=1;
    for(int i=1;i<=m;i++) {
        while(j<=n&&X[j]<=Y[i]) ins1(j++);
        ins2(i);
    }
    while(j<=n) ins1(j++);
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xugangfan/p/15129852.html