题解: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;
}

浙公网安备 33010602011771号