Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 2435  Solved: 1195

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且保证一定存在满足条件的乐曲
 
 
思路:
每一个子序列的权值和可以转化为两个前缀和之差。我们考虑以每一个位置为结尾的子序列,它的权值和可以看作是以该位置为结尾的前缀和减去它前面的某个前缀和。

那么想要这个子序列的权值和尽量大,那么就要前面的那个前缀和尽可能小。如果数目不够,就第2小。再不够,就第3小。

于是我们维护一个优先队列,维护3元组(v,r,k),v表示这个序列的权值和,r表示这个序列的结尾位置,k表示v是r结尾的符合条件的序列的第k大权值和

以每个位置为结尾的最大子序列权值和,每次取出堆顶时再放进堆中一个结尾位置相同的第k+1大的权值和。

这样k次就能出解。

这要求我们能够快速求出区间第k小,利用可持久化线段树即可。

时间复杂度O(klogn).

代码:

  //File Name: bzoj2006.cpp
//Author: long
//Mail: 736726758@qq.com
//Created Time: 2016年07月31日 星期日 14时12分42秒 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue> #define LL long long
#define hash _hash_ using namespace std; const int MAXN = + ; int h_num[MAXN],hash[MAXN],tot,top; void hash_init(){
sort(h_num+,h_num+top+);
tot = ;
hash[++tot] = h_num[];
for(int i=;i<=top;i++){
if(h_num[i] != h_num[i-])
hash[++tot] = h_num[i];
}
} int hash_find(int x){
int l = ,r = tot,mid;
while(l <= r){
mid = (l + r) >> ;
if(hash[mid] < x) l = mid + ;
else r = mid - ;
}
return l;
} struct T{
int v,r,k;
bool operator<(const T&a) const{
return v < a.v;
}
};
priority_queue<T> que;
struct Node{
int ls,rs,w;
Node(){ls = rs = w = ;}
}node[MAXN * ];
int a[MAXN],sum[MAXN],root[MAXN],sz,N,K,L,R; void update(int &i,int l,int r,int w){
node[++sz] = node[i];
i = sz;
node[i].w++;
if(l == r) return ;
int mid = (l + r) >> ;
if(w <= mid) update(node[i].ls,l,mid,w);
else update(node[i].rs,mid+,r,w);
} int query(int i,int j,int l,int r,int k){
if(l == r) return l;
int t = node[node[j].ls].w - node[node[i].ls].w;
int mid = (l + r) >> ;
if(t >= k) return query(node[i].ls,node[j].ls,l,mid,k);
else return query(node[i].rs,node[j].rs,mid+,r,k-t);
} void get(int i,int &l,int &r){
l = i - R, r = i - L;
if(l < ) l = ;
if(r < ) r = -;
} LL solve(){
sum[] = ;
top = ;
h_num[++top] = ;
for(int i=;i<=N;i++){
sum[i] = sum[i-] + a[i];
h_num[++top] = sum[i];
}
hash_init();
for(int i=;i<=N;i++)
sum[i] = hash_find(sum[i]);
sz = ;
root[] = root[] = ;
update(root[],,tot,sum[]);
for(int i=;i<=N;i++){
root[i+] = root[i];
update(root[i+],,tot,sum[i]);
}
while(!que.empty()) que.pop();
LL ans = ;
int now,l,r;
for(int i=L;i<=N;i++){
get(i,l,r);
if(r < ) continue;
//printf("i = %d l = %d r = %d\n",i,l,r);
now = hash[sum[i]] - hash[query(root[l],root[r+],,tot,)];
//printf("q = %d now = %d\n",query(root[l],root[r+1],1,tot,1),now);
que.push((T){now,i,});
}
T u;
while(true){
u = que.top();
que.pop();
//printf("u.v = %d\n",u.v);
ans += u.v;
K--;
if(!K) break;
get(u.r,l,r);
if(r - l + <= u.k) continue;
now = hash[sum[u.r]] - hash[query(root[l],root[r+],,tot,u.k+)];
que.push((T){now,u.r,u.k+});
}
return ans;
} int main(){
while(~scanf("%d %d %d %d",&N,&K,&L,&R)){
for(int i=;i<=N;i++) scanf("%d",&a[i]);
//cout << solve() << endl;
printf("%lld\n",solve());
}
return ;
}
 
 

bzoj2006 noi2010 超级钢琴 主席树 + 优先队列的更多相关文章

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

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

  2. [NOI2010]超级钢琴 主席树

    [NOI2010]超级钢琴 链接 luogu 思路 和12省联考的异或粽子一样. 堆维护n个左端点,每次取出来再放回去次 代码 #include <bits/stdc++.h> #defi ...

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

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

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

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

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

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

  6. 【BZOJ 2006】2006: [NOI2010]超级钢琴(RMQ+优先队列)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2792  Solved: 1388 Description 小 ...

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

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

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

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

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

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

随机推荐

  1. stash存储

    比如我的fsm_ngh分支,被a修改了,可是我本地还有没有提交的东西,就不能切换分支也不能下拉,也不能直接上传,否则分支会混乱. 这个时候stash的优点来了,先把你修改的暂存隐藏起来,然后pull远 ...

  2. C# checkboxlist的使用

    最近做项目,需要用到checklistbox这一控件,由于对这一控件并不是很熟悉,导致在此浪费了一点时间. http://www.cnblogs.com/hongfei/archive/2012/12 ...

  3. opencv中的.at方法

    opencv中的.at方法是用来获取图像像素值得函数: interpolation:差值 histogram:直方图

  4. Ubuntu 下载 & 编译 Android5.1 源码

    ustc & tsinghua android srchttps://lug.ustc.edu.cn/wiki/mirrors/help/aosphttps://mirrors.tuna.ts ...

  5. 【USB多路电源】layout

    USB多路电源的layout 图:第一次layout 缺点: 1.散,空间利用率不高: 2.不整齐: 3.没有符合左上进,右下出(当然也不必墨守): 4.输出排针没有放到最边上: 5.信号流向问题 6 ...

  6. oracle生成行方法

    数据库记录是行的集合 set of row, 那么如何如何生成集合呢? oracle中常用的是 递归查询(with ... union all ...) 以及 connect by(树形查询) htt ...

  7. SharePoint 2013 开发——搜索架构及扩展

    博客地址:http://blog.csdn.net/FoxDave SharePoint 2013高度整合了搜索引擎,在一个场中只有一个搜索服务应用程序(SSA).它集成了FAST,只有一个代码库 ...

  8. android技巧(三)屏幕适配

    屏幕适配策略: 1.控件使用wrap_content.match_parent控制某些视图组件的宽度和高度,而不是硬编码的尺寸. “wrap_content”系统就会将视图的宽度或高度设置成所需的最小 ...

  9. 如何在Kali Linux中搭建钓鱼热点

    文中提及的部分技术可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使用! 0×00 实验环境 操作系统:Kali 1.0 (VM) FackAP: easy-creds 硬件:NETGEAR wg ...

  10. JS运动基础(四) 碰撞运动

    碰撞运动撞到目标点,速度反转无重力的漂浮Div速度反转滚动条闪烁的问题过界后直接拉回来 加入重力反转速度的同时,减小速度纵向碰撞,横向速度也减小横向速度小数问题(负数) <!DOCTYPE HT ...