题解:uoj386 鸽子固定器

题意:给出 \(n\) 个物品和一个参数 \(m\),每个物品有两个属性 \(s,v\),再给出两个参数 \(1\le sd,sv\le 2\),现在要求你选出一个物品的集合 \(S\)\(|S|\le m\),要求 \((\sum\limits_{i\in S}s_i)^{sd} - (\max\limits_{i\in S} v_i - \min\limits_{i\in S}v_i) ^{sv}\) 最大值。

做法:

首先看到后面这个 \(\min,\max\),很自然的是将物品按 \(v\) 排序。

然后考虑枚举 \(\max\),先取 \(v\) 比他小但是前 \(m-1\) 大的元素,然后我们去进行替换,每次用前缀中第一个 \(s\) 比当前选中的 \(s\) 中最小的大的去替换目前选中的最小的 \(s\),一直去更新就做完了,这个可以用优先队列取最小,st 表 + 二分求第一个比最小值大的,复杂度 \(O(nm\log n)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5 + 5;
int n, m, ds, dv;
int get_ds(int x) {
	return (ds == 1 ? x : x * x);
}
int get_dv(int x) {
	return (dv == 1 ? x : x * x);
}
struct node {
	int s, v;
	friend bool operator<(node x, node y) {
		return x.v < y.v;
	}
} x[maxn];
int st[maxn][21], lg[maxn];
void prepare() {
	lg[0] = -1;
	for (int i = 1; i <= n; i++)
		st[i][0] = x[i].s, lg[i] = lg[i >> 1] + 1;
	for (int j = 1; (1 << j) <= n; j++)
		for (int i = 1; i + (1 << j) - 1 <= n; i++)
			st[i][j] = max(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
}
int query(int l, int r) {
	if(l > r)
		return 0;
	int k = lg[r - l + 1];
	return max(st[l][k], st[r - (1 << k) + 1][k]);
}
int fnd(int l, int r, int lim) {
	if(query(l, r) <= lim)
		return 0;
	int lx = 1, rx = r + 1;
//	cout << l << " " << r << " " << lim << endl;
	while(lx + 1 < rx) {
		int mid = lx + rx >> 1;
		if(query(mid, r) <= lim)
			rx = mid;
		else
			lx = mid;
	//	cout << l << " " << r << endl;
	}
	return lx;
}
struct node1 {
	int pos, val;
	friend bool operator<(node1 x, node1 y) {
		return x.val > y.val;
	}
};
int ans, cnt;
signed main() {
	ios::sync_with_stdio(false);
	cin >> n >> m >> dv >> ds;
	for (int i = 1; i <= n; i++)
		cin >> x[i].v >> x[i].s;
	sort(x + 1, x + n + 1);
//	for (int i = 1; i <= n; i++)
//		cout << x[i].s << " " << x[i].v << endl;
	prepare();
	for (int i = 1; i <= n; i++) {
		priority_queue<node1> q;
		int s = x[i].s; ans = max(ans, get_ds(s) + get_dv(0));
		q.push(node1{i, x[i].s});
		for (int j = i - 1; j >= max(1ll, i - m + 1); j--) {
			q.push(node1{j, x[j].s});
			s += x[j].s;
			ans = max(ans, get_ds(s) - get_dv(x[i].v - x[j].v));
	//		cout << i << " " << j << " " << get_ds(s) - get_dv(x[i].v - x[j].v) << endl;
		}
		int pos = i - m + 1;
		if(pos <= 1)
			continue;
		while(1) {
			if(q.top().pos == i)
				break;
			//cout << i << " " << pos << " " << q.top().pos << endl; 
			int p = fnd(1, pos - 1, q.top().val);
			if(p <= 0)
				break;
			pos = p;
		//	cout << i << " asd" << p << endl;
			s += x[p].s - q.top().val;
			ans = max(ans, get_ds(s) - get_dv(x[i].v - x[p].v));
			q.pop(), q.push(node1{p, x[p].s});
			cnt++;
		}
	//	cout << i << " " << cnt << endl;
	}
	cout << ans << endl;
	return 0;
}
posted @ 2025-07-23 09:45  LUlululu1616  阅读(8)  评论(0)    收藏  举报