CF1379C Choosing flowers

CF1379C Choosing flowers

容易发现如下性质:

1、答案要么是一堆 \(a​\) ,要么是一堆 \(a​\) 和若干 \(b​\)

2、如果要选 \(b\),一定只选一种物品的。考虑反证,如果选了两种 \(b\),显然都变成更大的那个是更优的。

一开始以为可以直接对着最大的 \(b\) 一波贪心搞定。后来发现不对,因为与之搭配的 \(a\) 很关键。在 \(a = 99,b = 99\)\(a = 1, b =100\) 之间显然前者更优。

因此我们需要对着每一种 \(b\) 都贪心一次。具体策略如下:先假定全选 \(a\),然后把所有满足 \(a_i \le b_{now}\)\(a_i\) 都换成 \(b_{now}\),显然这个过程可以对 \(a_i\) 排序后二分查找,再结合前缀和实现。时间复杂度 \(O(m \log m)\)

最后说两个细节:

1、满足条件的 \(a_i\) 中可能包含 \(a_{now}\)

2、当 \(n \lt m\) 时,\(a\) 一开始选不完,故 \(a_{now}\) 可能一开始没被选上。

3、条件判据最好写成 \(a_i \le b_{now}\) 而不是 \(a_i \lt b_{now}\),可以少调很多细节。

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
#define int ll 
using namespace std;
using ll = long long;
const int M = 1e5 * 2;
struct node{
	int a, b; 
	bool operator < (const node &other)const{
		return a < other.a;
	}
}s[M];
int n, m, T;
int sm[M], va[M];
namespace task{
	void Main(){
		int ans = 0, c = 0, mx = 0;
		cin >> n >> m;
		F(i, 1, m) {
			cin >> s[i].a >> s[i].b;
		}
		sort(s + 1, s + m + 1);
		F(i, 1, m){
			va[i] = s[i].a;	
			sm[i] = sm[i - 1] + va[i];
		}
		if(n < m){
			F(i, m - n + 1, m) ans += s[i].a;
			mx = ans;
			F(i, 1, m){
				int r, nw = 0;
				r = upper_bound(va + m - n + 1, va + m + 1, s[i].b) - va - 1;
				int num = r - (m - n + 1) + 1;
				if(num == 0) continue;
				if(i < m - n + 1){
					nw = ans - (sm[r] - sm[m - n]) + va[i] + (num - 1) * s[i].b;
				}
				else{
					if(r >= i){
						nw = ans - (sm[r] - sm[m - n] - va[i]) + (num - 1) * s[i].b;
					}
					else{
						nw = ans - (sm[r] - sm[m - n]) + num * s[i].b;
					}
				}
				mx = max(mx, nw);
			}
		}
		else{
			G(i, m, 1) ans += s[i].a;
			c = n - m; 
			mx = ans;
			F(i, 1, m){ 
				int r, nw = 0;
				r = upper_bound(va + 1, va + m + 1, s[i].b) - va - 1;
				if(r >= i){
					nw = ans - (sm[r] - va[i]) + (r - 1 + c) * s[i].b;
				}
				else{
					nw = ans - sm[r] + (r + c) * s[i].b;
				}
				mx = max(nw, mx);
			}
		} 
		cout << mx << '\n';
		F(i, 0, m) sm[i] = va[i] = 0; 
	}
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> T;
	while(T --) task::Main();
	return fflush(0), 0;
}
posted @ 2025-08-01 15:58  superl61  阅读(5)  评论(0)    收藏  举报