1、题意:给一个序列,让你取出k个不同的区间,要求长度在之间,问所有区间和的最大值

2、分析:这道题拿过来就能知道是要拿出前k个最大的区间,我们思考最暴力的做法,就是把这个所有的区间枚举出来算,取出前k个最大的,这个思路的复杂度很高,达到 很明显,这会超时,我们尝试换个角度,我们维护一个大根堆我们枚举所有的区间的左端点,然后我在 这个区间中选一个区间最大的,和大根堆中的最小数比较,如果大,那就加入堆,然后比较次大的,这样的复杂度呢? 是不是感觉卵用没有,但是这个算法的复杂度远远达不到上界,虽然说卡这个算法还是比较容易的,然后进一步思考,我们每次都是固定左端点的选一个,那么能不能再全局中选呢?依旧是这样,我们维护一个大根堆,这次我们要将每一个左端点的最大值先加入堆中,然后我们每次取出最大值,将这个区间分成左右两段,这样就等于拿走次左端点的最大值,加入次大值和第三大….那么如此类推,我们搞到前k大,加起来就是answer了,时间复杂度,,空间嘛,我们思考一下,每一次我们都会将一个区间分裂成两个,但是只会分裂两次,所以空间是,完美解决,撒花QAQ,另附一组小数据,藏在代码中ovo

//myy orz
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 2000010
#define LL long long
#define inf 214748364

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int a[M], sum[M];

struct Node{
    int i, L, id, R, res;

    inline bool operator < (const Node& rhs) const{
        return res < rhs.res;
    }
};
priority_queue<Node> Q;

struct myh{
    int val, id;

    inline bool operator < (const myh& rhs) const{
        return val < rhs.val;
    }
} q[M]; 

inline myh max(myh q1, myh q2){
    if(q1 < q2) return q2;
    return q1;
}

inline void build(int l, int r, int o){
    if(l == r){
        q[o].val = sum[l];
        q[o].id = l;
        return;
    }
    int mid = (l + r) / 2;
    build(l, mid, 2 * o);
    build(mid + 1, r, 2 * o + 1);
    q[o] = max(q[2 * o], q[2 * o + 1]);
}

inline myh query(int l, int r, int o, int x, int y){
    if(x <= l && r <= y) return q[o];
    int mid = (l + r) / 2;
    myh mx; mx.val = -inf;
    if(x <= mid) mx = max(mx, query(l, mid, 2 * o, x, y));
    if(y > mid) mx = max(mx, query(mid + 1, r, 2 * o + 1, x, y));
    return mx;
}

int main(){
    int n = read(), k = read(), L = read(), R = read();
    for(int i = 1; i <= n; i ++) a[i] = read(), sum[i] = a[i] + sum[i - 1];
    build(1, n, 1);
    for(int i = 1; i <= n; i ++){
        if(i + L - 1 > n) break;
        myh yy = query(1, n, 1, i + L - 1, min(n, i + R - 1));
        Node c = (Node){i, L, yy.id - i + 1, min(n, i + R - 1) - i + 1, yy.val - sum[i - 1]};
        Q.push(c);
    //  printf("%d\n", yy.id);
    }
    LL ans = 0;
    for(int i = 1; i <= k; i ++){
        Node x = Q.top(); Q.pop();
        ans += x.res;
        //printf("%d::", x.res);
        if(x.id > x.L){
            myh yy = query(1, n, 1, x.i + x.L - 1, x.i + x.id - 2);
            Node c = (Node){x.i, x.L, yy.id - x.i + 1, x.id - 1, yy.val - sum[x.i - 1]};
            Q.push(c);
        //  printf("%d %d\n", yy.val - sum[x.i - 1], x.id);
        }
        if(x.id < x.R){
            myh yy = query(1, n, 1, x.i + x.id, x.i + x.R - 1);
            Node c = (Node){x.i, x.id + 1, yy.id - x.i + 1, x.R, yy.val - sum[x.i - 1]};
            Q.push(c);
        //  printf("%d\n", yy.val - sum[x.i - 1]);
        }
    }
    printf("%lld\n", ans);
    return 0;
}
/*
10 13 3 7
595
384
-435
-197
-677
661
4
-100
-653
220

*/

BZOJ2006——[NOI2010]超级钢琴的更多相关文章

  1. bzoj2006 [NOI2010]超级钢琴 (及其拓展)

    bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...

  2. bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴

    http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...

  3. BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MB Submit: 3446  Solved: 1692 [Submit][Sta ...

  4. [BZOJ2006][NOI2010]超级钢琴(ST表+堆)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3679  Solved: 1828[Submit][Statu ...

  5. [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 3591  Solved: 1780[Submit][Statu ...

  6. bzoj2006 noi2010 超级钢琴 主席树 + 优先队列

    Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2435  Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送 ...

  7. BZOJ2006[NOI2010]超级钢琴——堆+主席树

    题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...

  8. 【贪心 计数】bzoj2006: [NOI2010]超级钢琴

    这么经典的贪心我怎么现在才做啊…… Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个 ...

  9. bzoj2006: [NOI2010]超级钢琴

    题意:给一个序列(n<=500000),要求选定k个不同区间,使得区间长度在L,R之间,并使得k个区间和之和最大,输出这个最大值. 刚拿到题的时候想的是,对于每个点,如果以它开头,那么之后的L- ...

随机推荐

  1. [luogu2964][USACO09NOV][硬币的游戏A Coin Game] (博弈+动态规划)

    题目描述 Farmer John's cows like to play coin games so FJ has invented with a new two-player coin game c ...

  2. codevs 2495 水叮当的舞步

    题目链接:水叮当的舞步 我现在开始发题目链接了(主要还是因为懒得整理题面)-- 这道题一开始是看到MashiroSky在写,于是我也开始写这道题了(说白了就是狙击他)-- 这道题看到这么小的范围当然给 ...

  3. Matlab中使用脚本和xml文件自动生成bus模块

    帮一个老师写的小工具 在一个大工程中需要很多bus来组织信号,而为了规范接口,需要定义很多BusObject,用Matlab语言手写这些BusObject比较费工夫 所以用xml配置文件来写,也便于更 ...

  4. 在intellj idea下用sbt的坑

    version : SBT 0.13.7 intellij 14 新建SBT项目以后无法编译,总是显示 Can not resolve symble stackoverflow 给出了暂时的解决办法. ...

  5. scalatest的userguide

    http://www.scalatest.org/user_guide 感觉功能很强大.这门语言有前途.

  6. C#基础系列——再也不用担心面试官问我“事件”了

    前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢? ...

  7. Xcode调试技巧(断点和重构)

    首先是最简单的普通断点有时候不知道是那个方法调用的崩溃的这个方法,传了个奇怪的值,打个断点就就可以在左侧工具栏里看到最近几个方法执行的循序,和那个方法调用的本方法,一般小问题在这里就可以解决啦~ 条件 ...

  8. 重写navigationController的push方法后,出现卡顿现象

    在使用navigation的pushViewController进行push的时候,两个页面间的动画会出现卡顿一下再推出的效果,是因为iOS7 viewController背景颜色的问题,看到大神的博 ...

  9. 自己写一个JS单向数据流动库----one way binding

    JS单向流动其实就是数据到视图的过程, 这几天突发奇想,想着弄一个插件, 把DOM结构使用JS进行描述: 因为DOM中的Class , content, id, attribute, 事件, 子元素全 ...

  10. ES6新特性:使用新方法定义javascript的Class

    ES6中定义类的方式, 就是ES3和ES5中定义类的语法糖,虽然也有些区别,但是整体定义类的方式更加简洁,类的继承更加方便, 如果想对ES6中的继承更加熟悉, 最好了解ES5中原型继承的方式, 博客园 ...