BZOJ2006 ST表 + 堆
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表 + 堆的更多相关文章
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)
[BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
[BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...
- [NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]
题面: 传送门 思路: 首先容易想到用堆维护的O(n2logn)暴力 那么肯定就是在这个基础上套数据结构了[愉快] 然而我因为过于蒟蒻......只想得到主席树暴力***过去的方法 大概就是把前缀和算 ...
- BZOJ2006:超级钢琴(ST表+堆求前K大区间和)
Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度 ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
随机推荐
- Running Web API using Docker and Kubernetes
Context As companies are continuously seeking ways to become more Agile and embracing DevOps culture ...
- java读取excel获取数据写入到另外一个excel
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- BZOJ2160拉拉队排练——回文自动机
题目描述 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多 ...
- nginx反向代理时配置访问密码
在有些情况下,我们需要对服务器上的某些资源进行限流或者禁止陌生人访问,我们可以通过nginx配置来对url添加访问密码. 效果如下 nginx 开启访问验证在 nginx 下,提供了 ngx_http ...
- Going Home POJ - 2195(费用流)
就是一个简单题 四个月前a的一道题,今天又看到了,再a一遍吧. 好吧 我想多了 用了bfs求最短路 其实不用的 因为没有障碍物 #include <iostream> #include ...
- Go Deeper HDU - 3715(2 - sat 水题 妈的 智障)
Go Deeper Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- Kindle支持文档类型
Kindle支持文档类型 Kindle个人文档服务目前只能转换并发送以下类型的文档:Microsoft Word (.doc, .docx) RTF文件(.rtf) HTML(.htm, .html) ...
- linux命令:查看系统版本
debian系统 (1) lsb_release -a No LSB modules are available. Distributor ID: Debian Description: Debia ...
- 【cf849ABC】
849A - Odds and Ends 问能否将序列划分为奇数个长度奇数的奇数开头奇数结尾的子区间. 一开始想dp..不过没必要. const int N=201000; int n,a[N]; i ...
- 【hdu 6161】Big binary tree(二叉树、dp)
多校9 1001 hdu 6161 Big binary tree 题意 有一个完全二叉树.编号i的点值是i,操作1是修改一个点的值为x,操作2是查询经过点u的所有路径的路径和最大值.10^5个点,1 ...