题目链接:

题目

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个法术一定是最大的。

代码

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<queue>
  5. #define X first
  6. #define Y second
  7. #define mp make_pair
  8. using namespace std;
  9. typedef __int64 LL;
  10. const int maxn=1e5+10;
  11. int arr[maxn];
  12. LL sumv[maxn];
  13. int n,k,l,r;
  14. struct Node{
  15. int i,l,r,pos;
  16. Node(int i,int l,int r,int pos):i(i),l(l),r(r),pos(pos){}
  17. bool operator < (const Node& tmp) const {
  18. return sumv[pos]-sumv[i-1]<sumv[tmp.pos]-sumv[tmp.i-1];
  19. }
  20. };
  21. LL dp[maxn][20];
  22. int pos[maxn][20];
  23. void rmq(){
  24. for(int i=0;i<=n;i++) dp[i][0]=sumv[i],pos[i][0]=i;
  25. for(int j=1;(1<<j)<=n+1;j++){
  26. for(int i=0;i+(1<<j)-1<=n;i++){
  27. if(dp[i][j-1]<dp[i+(1<<(j-1))][j-1]){
  28. dp[i][j]=dp[i+(1<<(j-1))][j-1];
  29. pos[i][j]=pos[i+(1<<(j-1))][j-1];
  30. }
  31. else{
  32. dp[i][j]=dp[i][j-1];
  33. pos[i][j]=pos[i][j-1];
  34. }
  35. }
  36. }
  37. }
  38. int Max(int l,int r){
  39. if(l>r) return 10086;
  40. int k=0;
  41. while((1<<k)<=r-l+1) k++; k--;
  42. if(dp[l][k]<dp[r-(1<<k)+1][k]){
  43. return pos[r-(1<<k)+1][k];
  44. }
  45. return pos[l][k];
  46. }
  47. int main(){
  48. while(scanf("%d%d%d%d",&n,&k,&l,&r)==4){
  49. sumv[0]=0;
  50. for(int i=1;i<=n;i++){
  51. scanf("%d",&arr[i]);
  52. sumv[i]=sumv[i-1]+arr[i];
  53. }
  54. rmq();
  55. LL ans=0;
  56. priority_queue<Node> pq;
  57. for(int i=1;i+r-1<=n;i++){
  58. pq.push(Node(i,i+l-1,i+r-1,Max(i+l-1,i+r-1)));
  59. }
  60. for(int i=n+2-r;i+l-1<=n;i++){
  61. pq.push(Node(i,i+l-1,n,Max(i+l-1,n)));
  62. }
  63. while(k--){
  64. while(pq.top().l>pq.top().r) pq.pop();
  65. Node nd=pq.top(); pq.pop();
  66. ans+=sumv[nd.pos]-sumv[nd.i-1];
  67. pq.push(Node(nd.i,nd.l,nd.pos-1,Max(nd.l,nd.pos-1)));
  68. pq.push(Node(nd.i,nd.pos+1,nd.r,Max(nd.pos+1,nd.r)));
  69. }
  70. printf("%I64d\n",ans);
  71. }
  72. return 0;
  73. }

Problem 1016 咒文卷轴 优先队列+前缀和+rmq的更多相关文章

  1. FOJ Problem 1016 无归之室

     Problem 1016 无归之室 Accept: 926    Submit: 7502Time Limit: 1000 mSec    Memory Limit : 32768 KB  Prob ...

  2. 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 ...

  3. 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 ...

  4. 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 号点出 ...

  5. FZU2013 A short problem —— 线段树/树状数组 + 前缀和

    题目链接:https://vjudge.net/problem/FZU-2013  Problem 2013 A short problem Accept: 356    Submit: 1083Ti ...

  6. Problem for Nazar CodeForces - 1151C (前缀和)

    Problem for Nazar Nazar, a student of the scientific lyceum of the Kingdom of Kremland, is known for ...

  7. CF802O-April Fools‘ Problem(hard)【wqs二分,优先队列】

    正题 题目链接:https://www.luogu.com.cn/problem/CF802O 题目大意 \(n\)天每条有\(a_i\)和\(b_i\). 每条可以花费\(a_i\)准备至多一道题, ...

  8. 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 ...

  9. CSU 1642 Problem B[难][前缀和]

    Description 已知两个正整数a和b,求在a与b之间(包含a和b)的所有整数的十进制表示中1出现的次数. Input 多组数据(不超过100000组),每组数据2个整数a,b.(1≤a,b≤1 ...

随机推荐

  1. Part 100 Func delegate in c#

    What is Func<T,TResult> in C#? In simple terms,Func<T,TResult> is just generic delegate. ...

  2. SQL Server 发布订阅 发布类型详解

    MicrosoftSQL Server 提供了三种复制类型. 每种复制类型都适合于不同应用程序的要求. 根据应用程序需要,可以在拓扑中使用一种或多种复制类型: 快照复制 事务复制 合并复制 为了帮助您 ...

  3. AccessHelper类

    using System; using System.Data; using System.Configuration; using System.Data.OleDb; using System.C ...

  4. blogs

    http://blogs.msdn.com/b/tess/archive/2008/02/04/net-debugging-demos-information-and-setup-instructio ...

  5. UI2_UITextField

    // // ViewController.h // UI2_UITextField // // Created by zhangxueming on 15/7/2. // Copyright (c) ...

  6. bootstrap-fileinput初体验

    原文:http://www.htmleaf.com/html5/html5muban/201505091801.html Document & Demo: http://plugins.kra ...

  7. ES6新增Promise

    1.promise概念 ES6 原生提供了 Promise 对象. 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提 ...

  8. 【leetcode】15. 3Sum

    题目描述: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...

  9. Map排序(按key/按value)

    package com.abc.test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collecti ...

  10. centos6.5安装fpm打包工具

    FPM功能简单说就是将一种类型的包转换成另一种类型.FPM的github:https://github.com/jordansissel/fpm 1.支持的源类型包: dir: 将目录打包成所需要的类 ...