Description
给出一个(a),选出(7)个数要求(P_1ge P_2ge P_3ge P_4ge P_5 ge P_6 ge P_7)
并且使得(P_1<P_2+P_3<P_4+P_5+P_6+P_7),最后令(7)个数的和最大
Solution
先对(a)数组降序排序
考虑(P_3),容易发现如果(P_3)的位置确定,那么(P_3)到(P_7)放在连续的一段一定是最优的
那么可以枚举(P_3)的位置,根据(P_2<P_4+P_5+P_6+P_7-P_3)找到(P_2)最左侧的可行位置(pos),并对([pos,P_3-1])这段区间进行赋值为(P_3)的位置
这样就能得出在(P_2)位置确定的情况下,(P_3)的最优位置,同理根据(P_1<P_3-P_2)找出最优的(P_1)更新答案
用线段树即可进行区间赋值和单点查询
Code
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 5e5 + 100;
int n;
ll a[N];
int cmp(ll x, ll y) {
return x > y;
}
int search(ll x) {
int l = 0, r = n;
while (l + 1 < r) {
int mid = (l + r) >> 1;
if (a[mid] <= x) r = mid;
else l = mid;
}
return r;
}
struct SegT {
#define lson x << 1
#define rson x << 1 | 1
#define mid ((l + r) >> 1)
int Min[N << 2], tag[N << 2];
void build(int l, int r, int x) {
if (l == r) {
Min[x] = n + 1;
tag[x] = n + 1;
return;
}
Min[x] = n + 1; tag[x] = n + 1;
build(l, mid, lson); build(mid + 1, r, rson);
}
void pushup(int x) {
Min[x] = min(Min[lson], Min[rson]);
}
void pushdown(int x) {
if (tag[x]) {
Min[lson] = min(Min[lson], tag[x]);
Min[rson] = min(Min[rson], tag[x]);
tag[lson] = min(tag[lson], tag[x]);
tag[rson] = min(tag[rson], tag[x]);
}
}
void modify(int L, int R, int c, int l, int r, int x) {
if (L <= l && r <= R) {
Min[x] = min(Min[x], c);
tag[x] = min(tag[x], c);
return;
}
pushdown(x);
if (L <= mid) modify(L, R, c, l, mid, lson);
if (R > mid) modify(L, R, c, mid + 1, r, rson);
pushup(x);
}
int query(int pos, int l, int r, int x) {
if (l == r) return Min[x];
pushdown(x);
if (pos <= mid) return query(pos, l, mid, lson);
else return query(pos, mid + 1, r, rson);
}
}T;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld", &a[i]);
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= n; ++i)
ls[i] = a[i];
ll ans = -1;
T.build(1, n, 1);
for (int i = 3; i <= n - 4; ++i) {
ll x = a[i + 1] + a[i + 2] + a[i + 3] + a[i + 4] - a[i] - 1;
int P2 = search(x);
if (P2 >= i) continue;
if (P2 == 1) P2++;
T.modify(P2, i - 1, i, 1, n, 1);
}
for (int i = 2; i < n - 4; ++i) {
int pos = T.query(i, 1, n, 1);
if (pos > n) continue;
ll tot = 0;
for (int j = pos; j <= pos + 4; ++j)
tot += a[j];
ll x = a[i] + a[pos] - 1;
int P1 = search(x);
if (a[P1] > x || P1 >= i) continue;
ans = max(ans, a[P1] + a[i] + tot);
}
printf("%lld
", ans);
}