Problem 1016 咒文卷轴 优先队列+前缀和+rmq
题目链接:
题目
Problem 1016 咒文卷轴
Time Limit: 3000 mSec
Memory Limit : 131072 KB
问题描述
小Y 是一个魔法师,有一天他获得了一卷神秘而古老的咒文卷轴,其由N个咒文构成,每一个咒文都有一个威力值ai, 现在小Y可以借助该卷轴释放强力的魔法,一个魔法必须由编号连续的一段的、长度大于等于L且小于等于R的咒文构成,该魔法的威力为构成该魔法的每一个咒文的威力的总和,现在小Y想要释放K个不同的魔法,问最大能产生多大的威力值,若两个魔法是相同的,则其咒文编号的集合应该完全相同。
输入
第一行包含四个整数N,K,L,R,分别表示咒文个数,需要释放的魔法个数,以及魔法包含的咒文术的下限与上限。
接下来n行,每行一个数字ai,表示按编号从小到大每个咒文的威力值。
N<=100000
K<=100000
-1000<=ai<=1000,1<=L<=R<=N并且保证一定能释放k种不同的法术。
输出
仅一行,表示K个不同魔法威力值之和的最大值。要换行。
样例
input
4 3 2 3
3
2
-6
8
output
11
题解
考虑一个简单的版本,0 <= ai <= 1000,那么对于i开始的魔法,结尾为[l, r]之间的魔法肯定是递增的,所以只需要用一个优先队列,先把n个位置的值都丢进去,然后每次取出最大的[i, r],然后在把[i, r - 1]丢回优先队列,直到r < l就不在丢进去,这样贪心能保证一定是从大到小取。
那么对于ai可以为负数的情况,前缀和就不满足递增了,然而对于一段区间[l, r]的和为两个前缀和相减,sum[r] - sum[l - 1]那么在左端点l固定的情况下,sum[r]越大越好,所以对于刚才那个问题等于是要取出优先队列中,区间[l, r]能取到前缀和值最大的位置mid,然后把区间在分成两部分[l, mid - 1], [mid + 1, r]丢回优先队列中,那么要维护一个区间最大值是个rmq问题,可以倍增st表O(nlogn)预处理一下,每次询问就是O(1)的,优先队列中的优先级就是区间最大值大的优先。这样就保证了取到的前k个法术一定是最大的。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define X first
#define Y second
#define mp make_pair
using namespace std;
typedef __int64 LL;
const int maxn=1e5+10;
int arr[maxn];
LL sumv[maxn];
int n,k,l,r;
struct Node{
int i,l,r,pos;
Node(int i,int l,int r,int pos):i(i),l(l),r(r),pos(pos){}
bool operator < (const Node& tmp) const {
return sumv[pos]-sumv[i-1]<sumv[tmp.pos]-sumv[tmp.i-1];
}
};
LL dp[maxn][20];
int pos[maxn][20];
void rmq(){
for(int i=0;i<=n;i++) dp[i][0]=sumv[i],pos[i][0]=i;
for(int j=1;(1<<j)<=n+1;j++){
for(int i=0;i+(1<<j)-1<=n;i++){
if(dp[i][j-1]<dp[i+(1<<(j-1))][j-1]){
dp[i][j]=dp[i+(1<<(j-1))][j-1];
pos[i][j]=pos[i+(1<<(j-1))][j-1];
}
else{
dp[i][j]=dp[i][j-1];
pos[i][j]=pos[i][j-1];
}
}
}
}
int Max(int l,int r){
if(l>r) return 10086;
int k=0;
while((1<<k)<=r-l+1) k++; k--;
if(dp[l][k]<dp[r-(1<<k)+1][k]){
return pos[r-(1<<k)+1][k];
}
return pos[l][k];
}
int main(){
while(scanf("%d%d%d%d",&n,&k,&l,&r)==4){
sumv[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
sumv[i]=sumv[i-1]+arr[i];
}
rmq();
LL ans=0;
priority_queue<Node> pq;
for(int i=1;i+r-1<=n;i++){
pq.push(Node(i,i+l-1,i+r-1,Max(i+l-1,i+r-1)));
}
for(int i=n+2-r;i+l-1<=n;i++){
pq.push(Node(i,i+l-1,n,Max(i+l-1,n)));
}
while(k--){
while(pq.top().l>pq.top().r) pq.pop();
Node nd=pq.top(); pq.pop();
ans+=sumv[nd.pos]-sumv[nd.i-1];
pq.push(Node(nd.i,nd.l,nd.pos-1,Max(nd.l,nd.pos-1)));
pq.push(Node(nd.i,nd.pos+1,nd.r,Max(nd.pos+1,nd.r)));
}
printf("%I64d\n",ans);
}
return 0;
}
Problem 1016 咒文卷轴 优先队列+前缀和+rmq的更多相关文章
- FOJ Problem 1016 无归之室
Problem 1016 无归之室 Accept: 926 Submit: 7502Time Limit: 1000 mSec Memory Limit : 32768 KB Prob ...
- 2013-2014 ACM-ICPC, NEERC, Southern Subregional Contest Problem F. Judging Time Prediction 优先队列
Problem F. Judging Time Prediction 题目连接: http://www.codeforces.com/gym/100253 Description It is not ...
- Codeforces Round #427 (Div. 2) Problem C Star sky (Codeforces 835C) - 前缀和
The Cartesian coordinate system is set in the sky. There you can see n stars, the i-th has coordinat ...
- HDU 6326.Problem H. Monster Hunter-贪心(优先队列)+流水线排序+路径压缩、节点合并(并查集) (2018 Multi-University Training Contest 3 1008)
6326.Problem H. Monster Hunter 题意就是打怪兽,给定一棵 n 个点的树,除 1 外每个点有一只怪兽,打败它需要先消耗 ai点 HP,再恢复 bi点 HP.求从 1 号点出 ...
- FZU2013 A short problem —— 线段树/树状数组 + 前缀和
题目链接:https://vjudge.net/problem/FZU-2013 Problem 2013 A short problem Accept: 356 Submit: 1083Ti ...
- Problem for Nazar CodeForces - 1151C (前缀和)
Problem for Nazar Nazar, a student of the scientific lyceum of the Kingdom of Kremland, is known for ...
- CF802O-April Fools‘ Problem(hard)【wqs二分,优先队列】
正题 题目链接:https://www.luogu.com.cn/problem/CF802O 题目大意 \(n\)天每条有\(a_i\)和\(b_i\). 每条可以花费\(a_i\)准备至多一道题, ...
- Gym - 101981M:(南京) Mediocre String Problem(回文树+exkmp)
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using ...
- CSU 1642 Problem B[难][前缀和]
Description 已知两个正整数a和b,求在a与b之间(包含a和b)的所有整数的十进制表示中1出现的次数. Input 多组数据(不超过100000组),每组数据2个整数a,b.(1≤a,b≤1 ...
随机推荐
- 北大ACM(POJ1006-Biorhythms)
Question:http://poj.org/problem?id=1006 问题点:孙子定理 Memory: 248K Time: 0MS Language: C++ Result: Accept ...
- Java实现邮箱找回密码 --转载
通过邮件找回密码功能的实现 1.最近开发一个系统,有个需求就是,忘记密码后通过邮箱找回.现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回.通过java发送邮件的 ...
- 【学习笔记】【C语言】进制
1. 什么是进制 是一种计数的方式,数值的表示形式 2. 二进制 1> 特点:只有0和1,逢2进1 2> 书写格式:0b或者0b开头 3> 使用场合:二进制指令\二进制文件,变量在内 ...
- c#高级编程第七版 学习笔记 第一章 .NET体系结构
第一章 .NET体系结构 本章内容: 编译和运行面向.NET的代码 Microsoft中间语言(Microsoft Intermediate Language,MSIL或简称IL)的优点 值 ...
- C#中 StringBuilder类 与 String类的区别---(转)
在找工作的时候,去了些公司,避免不了要面试和笔试.不过一般最起初的是笔试.我印象中有这样有一道题目:StringBuilder类与 String类的区别?那时候我不太清楚这两个类的区别,今天在看代 ...
- tcp 和 udp 缓冲区的默认大小及设置【转】
1. tcp 收发缓冲区默认值 [root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 4161536 ...
- 汇编中PTR常见的几种用法
汇编中PTR的用法确实是令人比较头疼的,我特意搜集了一些PTR的应用实例,可以从例子中揣摩出规律: 1.MOV WORD PTR [DI],OFFSET BUF1 2.SUB BYTE ...
- MySQL事务机制
事务机制的特性通常被概括为"ACID原则" A(Atomic) 原子性: 构成一个事务的所有语句应该是一个独立的逻辑单元,要么全部执行成功, 要么一个都不成功, 你不能只执行他们当 ...
- 如何将Log4Net 日志保存到mongodb数据库之实践
log4net的大名早有耳闻,一直没真正用过,这次开发APP项目准备在服务端使用log4net. 日志的数据量较大,频繁的写数据库容易影响系统整体性能,所以独立将日志写到mongodb数据库是不错的选 ...
- 30个HTML5学习资源
早在几个星期前,Adobe就发布了Dreamweaver CS5 HTML5 Pack的预览版下载.众所周知,HTML5在互联网领域掀起了一场大论战,并让Adobe的日子很难熬.HTML5致力于为前端 ...