洛谷 P11268 【MX-S5-T2】買東西題 做題記錄

coding_goat_qwq發表於2024-11-09

我不會貪心。

\(a\) 元的物品有 \(b\) 元的折扣,就相當於 \(a\) 元的物品有一張 \(a-b\) 元的優惠券。
因為一張優惠券是滿 \(w\) 元才可以用,所以可以用的物品在價格 \(a\) 上是一段區間 \([a,\inf]\)
有一個很樸素的想法是,將每一個物品最多能省多少錢先弄出來,然後用優惠券想辦法把省的最小的錢換成優惠券。
先將物品和優惠券按滿多少可以有優惠排序,再列舉優惠券,最後就是按照上面說的逐步加進去就好了。
想要快速求出最小值可以用優先佇列,如果到最後還用不到優惠券的記得把打得折加進去。
時間複雜度 \(O(n \log n)\)

點選檢視程式碼
#include<bits/stdc++.h>
#define int ll
#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define inn(i,n,a) For(i,1,n) a[i]=read();

#define ll long long
#define i128 __int128

using namespace std;
inline int read() {
	int xx= 0;int f= 1;
	char c = getchar();
	while(c<'0'||c>'9') { 
		if(c=='-') f= -1;
		c= getchar();
	}
	while(c>='0'&&c<='9') {
		xx= (xx<<1)+(xx<<3)+(c^48);
		c= getchar();
	}
	return xx*f;
}
#define maxn 1000050
int n,m;
struct node {
	int x,y;
}a[maxn],b[maxn];
bool cmp(node a,node b) {
	return a.x==b.x?a.y>b.y:a.x>b.x;
}
int res=0;
signed main() {
	in2(n,m);
	For(i,1,n) {
		int x,y;
		in2(x,y);
		a[i].x=x,a[i].y=x-y;
		res+=a[i].x;
	}
	For(i,1,m) {
		in2(b[i].x,b[i].y);
	}
	int i=1;
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+m+1,cmp);
	priority_queue<int,vector<int>,greater<int> > q;
	For(j,1,m){
		while(i<=n&&a[i].x>=b[j].x) q.push(a[i].y),i++;
		if(q.size()&&q.top()<b[j].y) {
			q.pop();
			q.push(b[j].y);
		}
	}
	while(i<=n) q.push(a[i].y),i++;
	while(q.size()) res-=q.top(),q.pop();
	cout<<res;
}