zoukankan      html  css  js  c++  java
  • 2020-2021 Winter Petrozavodsk Camp, Day 9 Contest-线段树

    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);
    }
    
  • 相关阅读:
    ffmpeg参数说明
    【FFmpeg】FFmpeg常用基本命令
    ffmpeg最全的命令参数
    数据库总结
    linux redis安装及JAVA使用jedis
    记录一次工作中jvm被linux杀死的调查
    ExecutorService线程池submit的使用
    java四种引用与回调函数
    java排序
    NIO教程笔记
  • 原文地址:https://www.cnblogs.com/cychester/p/14502651.html
Copyright © 2011-2022 走看看