cychester

2020-2021 Winter Petrozavodsk Camp, Day 9 Contest-线段树

Description

给出一个\(a\),选出\(7\)个数要求\(P_1\ge P_2\ge P_3\ge P_4\ge 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\n", ans);
}

posted on 2021-03-08 22:13  cychester  阅读(300)  评论(0编辑  收藏  举报

导航