80分求助
查看原帖
80分求助
464004
ZepX_D楼主2024/11/18 14:13

赛时累计 2h 想出来的贪心,大样例全部通过。

具体策略是先对商品按 aibia_i-b_i 从小到大排序,然后每回找优惠券 jj,满足 vj>aibi,wjaiv_j>a_i-b_i,w_j\le a_iwjw_j 最大。 同时有一个以 vv 为关键字的小根堆,维护已经用过的优惠券,每回对于 vaibiv\le a_i-b_i 的看能不能反悔。

#include <bits/stdc++.h>
#define fr first
#define se second
#define Un unsigned
#define LL long long
#define pb push_back
#define pii pair<int,int>
#define pLi pair<LL,int>
#define pLL pair<LL,LL>
#define __ __int128
#define LD long double
#define VE vector<LL>
#define DB double
#define Ve vector<int>

using namespace std;

inline LL read()
{
	LL x = 0,f = 1;char ch = getchar();
	while(!isdigit(ch)) (ch == '-') && (f = -1),ch = getchar();
	while(isdigit(ch)) x = x*10+ch-48,ch = getchar();
	return x*f;
}

const int N = 1e6+5,INF = 2e9;
int a[N],b[N],w[N],v[N],c[N];
multiset < pii > s;
priority_queue < pii,vector<pii>,greater<pii> > q1,q2;

int main()
{
	int n = read(),m = read();LL sum = 0;
	for (int i = 1;i <= n;i++) a[i] = read(),b[i] = read(),c[i] = i;
	for (int i = 1;i <= m;i++) w[i] = read(),v[i] = read(),s.insert({w[i],v[i]}),q1.push({v[i],w[i]});
	sort(c+1,c+n+1,[](int x,int y){return a[x]-b[x] < a[y]-b[y];});
	for (int i = 1;i <= n;i++)
	{
		while (q1.size() && q1.top().fr <= a[c[i]]-b[c[i]])
		{
			auto it = s.find({q1.top().se,q1.top().fr});
			if(it != s.end()) s.erase(it);
			q1.pop();
		}
		while (q2.size() && q2.top().fr <= a[c[i]]-b[c[i]])
		{
			auto it = s.upper_bound({q2.top().se,INF});
			if (it != s.begin())
			{
				it--,sum = sum+q2.top().fr-(*it).se;
				q2.push({(*it).se,(*it).fr}),s.erase(it);
			}
			q2.pop();
		}
		auto it = s.upper_bound({a[c[i]],INF});
		if (it != s.begin())
		{
			it--,sum += a[c[i]]-(*it).se;
			q2.push({(*it).se,(*it).fr}),s.erase(it);
		}
		else sum += b[c[i]];
	}
	cout << sum;
	return 0;
}
2024/11/18 14:13
加载中...