CodeForces 799 E. Aquarium decoration 贪心 Set

版权声明:_ https://blog.csdn.net/lunch__/article/details/82947809

题意

  • 两个人每个人喜欢一些物品,从 n n 个物品恰好选 m m 个,使每个人喜欢的物品至少有 k k 个,最小化物品价值,不存在方案输出 1 -1 .

我们先贪心选出令两个人都有 k k 个喜欢的物品并且价值最小的物品集合

然后如果此时不足 m m 个 就从剩下的没选的选出最小的几个到 m m 个为止

如果超过了 m m

那么就每次找到 A , B A,B 都喜欢没有被选并且权值最小的物品

来替换选中的物品中只有 A A 喜欢和只有 B B 喜欢的权值最大的物品

如果不能替换到 m m 个那么肯定是无解了

如果替换到了 m m 个 那么还有一种方法可以让答案变得更优

用一个没被选的 A , B A,B 都喜欢的加上另一个没被选的最小权值

来替换一个选了的只有 A A 喜欢和只有 B B 喜欢的最大权值

这样子替换到权值不换变小为止就做完了

其中找各种最大最小可以用 S t d : : S e t Std::Set 实现

Codes

#include<bits/stdc++.h>
#include<bits/extc++.h>

#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define FOR(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define debug(x) cout << #x << " = " << x << endl
#define mem(a, b) memset(a, b, sizeof(a))
#define cpy(a, b) memcpy(a, b, sizeof(a))
#define min(a, b) (a < b ? a : b)
#define max(a, b) (b < a ? a : b)
#define inf (0x3f3f3f3f)
#define INF (1e18)
#define pb push_back
#define mp make_pair
#define x first
#define y second

typedef unsigned long long ull;
typedef unsigned int uint;
typedef long long ll;
typedef std::pair<ll, int> PLI;
typedef std::pair<int, int> PII;
typedef long double ldb;
typedef double db;

namespace IO {
#define getc() ((S_ == T_) && (T_ = (S_ = Ch_) + fread(Ch_, 1, Buffsize, stdin), S_ == T_) ? 0 : *S_ ++)
#define putc(x) *nowps ++ = (x)
	const uint Buffsize = 1 << 15, Output = 1 << 23;
	static char Ch_[Buffsize], *S_ = Ch_, *T_ = Ch_;
	static char Out[Output], *nowps = Out;
	inline void flush(){fwrite(Out, 1, nowps - Out, stdout); nowps = Out;}
	template<class T>inline void read(T &_) {
		_ = 0; static char __; T ___ = 1;
		for(__ = getc(); !isdigit(__); __ = getc()) if(__ == '-') ___ = -1;
		for(; isdigit(__); __ = getc()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
		_ *= ___;
	}
	template<class T>inline void write(T _, char __ = '\n') {
		if(!_) putc('0');
		if(_ < 0) putc('-'), _ = -_;
		static uint sta[111], tp;
		for(tp = 0; _; _ /= 10) sta[++ tp] = _ % 10;
		for(; tp; putc(sta[tp --] ^ 48)); putc(__);
	}
	template<class T>inline bool chkmax(T &_, T __) {return _ < __ ? _ = __, 1 : 0;}
	template<class T>inline bool chkmin(T &_, T __) {return _ > __ ? _ = __, 1 : 0;}
}

using namespace std;
using namespace IO;

const int N = 2e5 + 10;

bitset<N> visa, visb, visall, choose;
set<PII> T, aa, bb, alll;
vector<PII> all, A, B;

int cnt, n, m, k, a, b, tmpa, tmpb, v[N];
int ovo[N], tpp, fuck[N], tp;

ll ans;

int main() {
	read(n), read(m), read(k);
	For(i, 1, n) read(v[i]), T.insert(mp(v[i], i));
	read(a); For(i, 1, a) {
		int x; read(x); visa[x] = 1;
		A.pb(mp(v[x], x));
	}
	read(b); For(i, 1, b) {
		int x; read(x); visb[x] = 1;
		if(visa[x]) visall[x] = 1, all.pb(mp(v[x], x));
		B.pb(mp(v[x], x));
	}
	sort(A.begin(), A.end()), sort(B.begin(), B.end()), sort(all.begin(), all.end());
	//for(auto v : A) cout << v.y << ' ' ; cout << endl;
	//for(auto v : B) cout << v.y << ' ' ; cout << endl;
	if(a < k || b < k) return puts("-1"), 0;
	For(i, 0, k - 1) {
		PII now = A[i]; 
		if(choose[now.y]) continue;
		if(visall[now.y]) alll.insert(now), ++ tmpb;
		else aa.insert(now);
		choose[now.y] = true; ++ cnt; ++ tmpa;
	}
	For(i, 0, k - 1) {
		if(tmpb == k) break;
		PII now = B[i];
		if(choose[now.y]) continue;
		if(visall[now.y]) alll.insert(now), ++ tmpa;
		else bb.insert(now);
		choose[now.y] = true; ++ cnt; ++ tmpb;
	}
	while(tmpa > k) {
		auto it = aa.end(); -- it;
		auto now = *it; aa.erase(it);
		choose[now.y] = 0; -- cnt; -- tmpa;
	}
	while(cnt < m) {
		PII now = *T.begin(); T.erase(now);
		if(choose[now.y]) continue;
		choose[now.y] = true; ++ cnt;
	}
	if(cnt > m) {
		int now = 0, len = all.size();
		while(cnt > m && !aa.empty() && !bb.empty() && now < len) {
			if(choose[all[now].y]) {++ now; continue;}
			auto ita = aa.end(), itb = bb.end(); -- ita, -- itb;
			auto itA = *ita, itB = *itb;
			choose[itA.y] = choose[itB.y] = 0;
			aa.erase(ita), bb.erase(itb);
			choose[all[now ++].y] = true; -- cnt;
		}
		if(cnt > m) return puts("-1"), 0;
	}
	for(auto it = T.begin(); it != T.end(); ++ it)
		if(!choose[(*it).y])
			fuck[++ tp] = (*it).y;
	for(auto v : all) 
		if(!choose[v.y])
			ovo[++ tpp] = v.y;
	int qaq = 1;
	for(int i = 1; i <= tp; ++ i) {
		if(aa.empty() || bb.empty() || qaq > tpp) break;
		auto ita = aa.end(), itb = bb.end(); -- ita, -- itb;
		auto itA = *ita, itB = *itb;
		int nowa = fuck[i], nowb = ovo[qaq];
		if(nowa == nowb) continue;
		if(itA.x + itB.x <= v[nowa] + v[nowb]) break;
		choose[itA.y] = choose[itB.y] = 0;
		aa.erase(ita), bb.erase(itb); ++ qaq;
		choose[nowa] = choose[nowb] = true;
	}
	if(cnt != m) return puts("-1"), 0;
	int tmp = 0;
	For(i, 1, n) if(choose[i]) ans += v[i];//, cout << i << endl;;I
	write(ans);
	return flush(), 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/82947809