https://www.lydsy.com/JudgeOnline/problem.php?id=2006

题意:在长度N的序列中求K段长度在L到R之间的区间,使得他们的和最大

很容易想到要求一个前缀和。

然后每一个位置i就对应后面的一段i + L - 1 ~ i + R - 1的区间,如果考虑暴力的话,就把每一个值对应的区间内所有的值再全部加入优先队列,取出K个。

看了下数据范围发现不可行。

考虑ST表求最值,在每一个对应区间内找一个最大值,仔细一想也觉得不可行,因为一个区间内的次大值很有可能是会对答案产生贡献的。

事实上我们对ST表加入一点小操作,使得他维护的是静态区间内的最大值下标,rmq(l,r)返回的是l到r区间内最大值的下标p,我们首先将N个三元组i,l,r加入堆,他的贡献是pre[rmq(l,r)] - pre[i - 1],将贡献从大到小排序,当我们处理完一个三元组的时候,再加入分裂开的三元组i,l,p - 1与i,p + 1,r,也就是说,当区间内最大值计算完之后,就往堆中放入一个次大值和次次大值,以此类推即可。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 5e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,L,R;
int a[maxn];
LL pre[maxn];
const int SP = ;
int Max[maxn][SP];
int mm[maxn];
void initRMQ(int n,LL b[]){
mm[] = -;
for(int i = ; i <= n; i ++){
mm[i] = ((i & (i - )) == )?mm[i - ] + :mm[i - ];
Max[i][] = i;
}
for(int j = ; j <= mm[n]; j ++){
for(int i = ; i + ( << j) - <= n ; i ++){
int x = Max[i][j - ],y = Max[i + ( << (j - ))][j - ];
Max[i][j] = b[x] > b[y]?x:y;
}
}
}
int rmq(int x,int y,LL b[]){
int k = mm[y - x + ];
return b[Max[x][k]] > b[Max[y - ( << k) + ][k]]?Max[x][k]:Max[y - ( << k) + ][k];
}
struct node{
int l,r,o;
node(){}
node(int l,int r,int o):l(l),r(r),o(o){}
LL ans(){
return pre[rmq(l,r,pre)] - pre[o - ];
}
friend bool operator < (node a,node b){
return a.ans() < b.ans();
}
};
int main(){
N = read(); M = read(); L = read(); R = read();
for(int i = ; i <= N ; i ++){
a[i] = read();
pre[i] = pre[i - ] + a[i];
}
initRMQ(N,pre);
priority_queue<node>Q;
for(int i = ; i <= N ; i ++){
if(i + L - > N) break;
Q.push(node(i + L - ,min(i + R - ,N),i));
}
LL ans = ;
while(M--){
node u = Q.top(); Q.pop();
ans += u.ans();
int p = rmq(u.l,u.r,pre);
if(p != u.l) Q.push(node(u.l,p - ,u.o));
if(p != u.r) Q.push(node(p + ,u.r,u.o));
}
Prl(ans);
return ;
}

BZOJ2006 ST表 + 堆的更多相关文章

  1. BZOJ 2006: [NOI2010]超级钢琴 ST表+堆

    开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...

  2. [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)

    [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...

  3. 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)

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

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

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

  5. 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆

    [BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...

  6. [NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]

    题面: 传送门 思路: 首先容易想到用堆维护的O(n2logn)暴力 那么肯定就是在这个基础上套数据结构了[愉快] 然而我因为过于蒟蒻......只想得到主席树暴力***过去的方法 大概就是把前缀和算 ...

  7. BZOJ2006:超级钢琴(ST表+堆求前K大区间和)

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

  8. bzoj 2006 [NOI2010]超级钢琴——ST表+堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...

  9. BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]

    题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...

随机推荐

  1. Build 2017 Revisited: .NET, XAML, Visual Studio

    For the next couple months we're going to revisit Build 2017, each post focusing on different aspect ...

  2. com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@1035079 -- APPARENT DEADLOCK!!! Complete Status:

    com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@1035079 -- APPARENT DEADLOCK!!! C ...

  3. 洛谷P3389 【模板】高斯消元法

    P3389 [模板]高斯消元法 题目背景 Gauss消元 题目描述 给定一个线性方程组,对其求解 输入输出格式 输入格式: 第一行,一个正整数 n 第二至 n+1行,每行 n+1 个整数,为a1​,a ...

  4. Nginx 防盗链 secure_link 模块

    L:76 需要通过 --with-http_secure_link_module 编译进Nginx secure_link 指令 Syntax: secure_link expression; Def ...

  5. 使用JSch远程执行shell命令

    package com.nihaorz.jsch; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import ...

  6. BZOJ2877 NOI2012魔幻棋盘(二维线段树)

    显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数).于是一维情况直接线段树维护差分序列即可. 容易想到将该做法拓展到二维.于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形 ...

  7. SpringMVC 集成Log4j

    项目地址:https://github.com/xiaoqiu-duan/DataProject.git 1.添加jar <dependency> <groupId>org.s ...

  8. windows 虚拟环境下 安装 mysql 引擎一系列错误处理

    报错现象 运行django 报错. 很明显是缺少引擎 下载引擎 django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb m ...

  9. 自学Linux命令行与Shell脚本之路

    自学Linux命令行与Shell脚本之路[第一回]:初识Linux   1.1 自学Linux Shell1.1-Linux初识 1.2 自学Linux Shell1.2-Linux目录结构 1.3  ...

  10. 【THUWC2017】随机二分图(动态规划)

    [THUWC2017]随机二分图(动态规划) 题面 BZOJ 洛谷 题解 如果每天边的限制都是\(0.5\)的概率出现或者不出现的话,可以把边按照二分图左侧的点的编号排序,然后设\(f[i][S]\) ...