BZOJ2006 [NOI2010] ST表 + 堆

2 篇文章 0 订阅
2 篇文章 0 订阅

Description

    小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出 n 个音符,编号为 1 至 n。第i个音符的美妙度为 Ai,其中 Ai 可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于 L 且不多于 R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由 k 个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由 k 个不同的超级和弦组成。
    我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
大值是多少。

Input

    第一行包含四个正整数 n, k, L, R。其中 n 为音符的个数,k 为乐曲所包含的超级和弦个数,L和R分别是超级和弦所包含音符个数的下限和上限。 接下来 n 行,每行包含一个整数 Ai ,表示按编号从小到大每个音符的美妙度。

Output

只有一个整数,表示乐曲美妙度的最大值。

Sample Input

4 3 2 3
3
2
-6
8

Sample Output

11

[样例说明]

共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。

HINT

N <= 500,000,k <= 500,000
-1000 <= Ai <= 1000, 1 <= L <= R<= N且保证一定存在满足条件的乐曲


Solution :

    这道题需要找到子区间第 K 大的值,那我们先考虑如何给定一个端点去找最大的区间,首先算区间和很容易前缀,然后是给定区间大小寻找区间,因为一个端点是定的,这里我定的是左端点, 我们只需要去寻找右区间的前缀的最大值,从公式是很容易看出dismax=max(pre[i]pre[now]) now+L1inow+R1 找最大值的话,你可以线段树什么花式找都可以,但毕竟只是要一个最大值,为什么不用ST表呢,简单好些, O(1) 查询,于是我们就有了找到最大值的用法。
    现在考虑找到第 K 大的用法,我们可以用个堆维护信息,每次维护 now, ls , rs , pos , val 五个信息, now 表示该状态的左端点, ls rs 表示该状态在 ls rs 的区间寻找最大值, pos 表示在 pos 位置找到了最大值, val 表示该状态的最大值。当我们已经记录了该状态的答案,我们就不需要 pos 的信息, 也就是为了不再使用 pos 的信息,我们把状态分成 (now,ls,pos1,pos,val) (now,pos+1,rs,pos′′,val′′) ,这样就避开了 pos 。然后就愉快的做出来了。



Code :

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#include <queue>
#define LL long long 
using namespace std;

inline int read() {
    int i = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') f = -1; ch = getchar();
    }
    while(isdigit(ch)) {
        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
    }
    return i * f;
}

const int MAXN = 5e5 + 5;
int a[MAXN], pre[MAXN], n, k, Log[MAXN], mx[20][MAXN];
LL ans;

struct point {
    int l, r, i, val, pos;
    point() {}
    point(int _l, int _r, int _i, int _val, int _pos) : l(_l), r(_r), i(_i), val(_val), pos(_pos) {}
    bool operator < (const point & a) const {
        return val < a.val;
    }
};

inline int new_max(int x, int y) {
    return pre[x] > pre[y] ? x : y;
}

inline void ST() {
    Log[0] = -1;
    for(int i = 1; i <= n; ++i) Log[i] = Log[i >> 1] + 1;
    for(int i = 1; i <= n; ++i) mx[0][i] = i;
    for(int j = 1; (1 << j) <= n; ++j)
        for(int i = 1; i + (1 << j) - 1 <= n; ++i)
            mx[j][i] = new_max(mx[j - 1][i], mx[j - 1][i + (1 << j - 1)]);
}

inline int find(int l, int r) {
    int k = Log[r - l + 1];
    return new_max(mx[k][l], mx[k][r - (1 << k) + 1]);
}

priority_queue<point> q;

inline void wr(LL x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) wr(x / 10);
    putchar(x % 10 + '0');
}

int main() {
    n = read(), k = read(); int L = read(), R = read();
    for(int i = 1; i <= n; ++i) a[i] = read(), pre[i] = pre[i - 1] + a[i];
    ST();
    for(int i = 1; i <= n; ++i)
        if(i + L - 1 <= n) {
            int ls = i + L - 1, rs = min(i + R - 1, n);
            int pos = find(ls, rs), val = pre[pos] - pre[i - 1];
            q.push(point(ls, rs, i, val, pos));
        }
        else break;

    while(!q.empty() && k) {
        --k;
        point now = q.top(); q.pop();
        ans += now.val;
        point ls = now, rs = now;
        ls.r = now.pos - 1;
        if(ls.r >= ls.l)
            ls.pos = find(ls.l, ls.r), ls.val = pre[ls.pos] - pre[ls.i - 1], q.push(ls);
        rs.l = now.pos + 1;
        if(rs.r >= rs.l)
            rs.pos = find(rs.l, rs.r), rs.val = pre[rs.pos] - pre[rs.i - 1], q.push(rs);
    }
    wr(ans);
}
购物商城项目采用PHP+mysql有以及html+css jq以及layer.js datatables bootstorap等插件等开发,采用了MVC模式,建立一个完善的电商系统,通过不同用户的不同需求,进行相应的调配和处理,提高对购买用户进行配置….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值