「CF521D」Shop

传送门
Luogu

解题思路

当只有第三类操作时,我们显然先进行val较大的操作,这是显然的。
那么就考虑把所有的操作都转变为第三类操作。
第一类操作,显然很容易变为第二类操作:单点维护最大的最终结果,然后改为加法就好了。
问题在于第二类操作如何转换。
其实也是贪心,我们对于同一个位置的第二类操作,优先进行val值较大的,把较小的分母留给较大的分子使得答案最优。

细节注意事项

  • 实现起来有点繁琐。

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
	s = 0; int f = 0; char c = getchar();
	while (!isdigit(c)) f |= c == '-', c = getchar();
	while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
	s = f ? -s : s;
}
typedef long long LL;
const int _ = 100010;
int n, m, k, n1, n2, n3, x[_];
struct node{ int t, id, x; LL fz, fm; }t1[_], t2[_], t3[_], ans[_];
inline bool cmp1(const node& a, const node& b) { return a.x == b.x ? a.fz < b.fz : a.x < b.x; }
inline bool cmp2(const node& a, const node& b) { return a.x == b.x ? a.fz > b.fz : a.x < b.x; }
inline bool cmp3(const node& a, const node& b) { return a.fz * b.fm > b.fz * a.fm; }
inline bool cmp4(const node& a, const node& b) { return a.t < b.t; }
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
#endif
	read(n), read(m), read(k);
	for (rg int i = 1; i <= n; ++i) read(x[i]);
	for (rg int t, xi, val, i = 1; i <= m; ++i) {
		read(t), read(xi), read(val);
		if (t == 1 && val > x[xi]) t1[++n1] = (node) { t, i, xi, val, 1 };
		if (t == 2) t2[++n2] = (node) { t, i, xi, val, 1 };
		if (t == 3) t3[++n3] = (node) { t, i, xi, val, 1 };
	}
	sort(t1 + 1, t1 + n1 + 1, cmp1);
	int qwq = 0;
	for (rg int i = 1; i <= n1; ++i)
		if (t1[i].x != t1[i + 1].x) t1[++qwq] = t1[i];
	n1 = qwq;
	for (rg int i = 1; i <= n1; ++i)
		t1[i].fz -= x[t1[i].x], t2[++n2] = t1[i];
	sort(t2 + 1, t2 + n2 + 1, cmp2);
	LL sum = 0;
	for (rg int i = 1; i <= n2; ++i) {
		if (t2[i].x != t2[i - 1].x) sum = x[t2[i].x];
		t2[i].fm = sum, sum += t2[i].fz;
	}
	for (rg int i = 1; i <= n3; ++i) --t3[i].fz;
	for (rg int i = 1; i <= n2; ++i) t3[++n3] = t2[i];
	sort(t3 + 1, t3 + n3 + 1, cmp3);
	int cnt = min(n3, k);
	for (rg int i = 1; i <= cnt; ++i) ans[i] = t3[i];
	printf("%d\n", cnt);
	sort(ans + 1, ans + cnt + 1, cmp4);
	for (rg int i = 1; i <= cnt; ++i)
		printf("%d%c", ans[i].id, " \n"[i == cnt]);
	return 0;
}

完结撒花 \(qwq\)

posted @ 2019-10-28 15:35  Sangber  阅读(149)  评论(0编辑  收藏  举报