【单调队列】【3-21个人赛】【problmeB】
Problem B
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 170 Accepted Submission(s) : 29
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
例如6个亮度为: 1, -3, 5, 1, -2, 3的灯泡,
当A=2,B=2或3时 S=5+1=6
当A=3,B=4时 S=5+1+(-2)+3=7
Input
接下来为T组数组,每组的格式为:
第一行三个整数N,A,B(1<=A<=B<=N<=500000)。
第二行为N个整数,每个整数用空格隔开,表示这N个灯泡的亮度。|亮度|<=10000。
Output
Sample Input
2
6 2 2
1 -3 5 1 -2 3
6 3 4
1 -3 5 1 -2 3
Sample Output
6
7
枚举连续序列的初始点 并找到【初始点+A-1,初始点+B-1】区间中的sum[i]的最大值 更新ANS即可
复杂度N*(B-A)
但是我们可以看出 在找最大值时 这个区间是固定不动的,而且随着枚举初始点向左移,所以可以用单调队列来维护这个区间最大值
是单调队列的一个常用法
单调队列介绍在这里
http://blog.csdn.net/justmeh/article/details/5844650
1.不加二分
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
const int maxn=500000+5;
using namespace std;
struct node
{
long long num;
int pos;
};
long long N,A,B;
long long a[maxn],sum[maxn];
node queue[maxn];
int s=1,t=0;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
void input()
{
s=1;t=0;
scanf("%d%d%d",&N,&A,&B);
for(int i=1;i<=N;i++)
{
scanf("%I64d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
}
void PUSH(long long aa,int bb)
{
while(t!=s-1&&queue[t].num<=aa) t--;
queue[++t].num=aa,queue[t].pos=bb;
}
void solve()
{
long long ans;
for(int i=A;i<=B;i++)
PUSH(sum[i],i);
ans=queue[s].num-sum[0];
for(int i=2;i+A-1<=N;i++)
{
if(i+B-1<=N)
PUSH(sum[i+B-1],i+B-1);
while(queue[s].pos<i+A-1)
s++;
if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1];
}
printf("%I64d\n",ans);
}
int main()
{
// init();
int T;
cin>>T;
while(T--)
{
input();
solve();
}
return 0;
}
2.加二分
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
const int maxn=500000+5;
using namespace std;
struct node
{
long long num;
int pos;
};
long long N,A,B;
long long a[maxn],sum[maxn];
node queue[maxn];
int s=1,t=0;
void init()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
void input()
{
s=1;t=0;
scanf("%d%d%d",&N,&A,&B);
for(int i=1;i<=N;i++)
{
scanf("%I64d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
}
int FIND(int s,int t,int p)
{
int m;
while(s<t)
{
int m=(s+t)/2;
if(queue[m].num<p) t=m;
else s=m+1;
}
if(queue[s].num<=p) return s-1;
else return s;
}
void PUSH(long long aa,int bb)
{
int k=0;
if(s>t)
queue[++t].num=aa,queue[t].pos=bb;
else {
t=FIND(s,t,aa);
queue[++t].num=aa,queue[t].pos=bb;
}
}
void solve()
{
long long ans;
for(int i=A;i<=B;i++)
PUSH(sum[i],i);
ans=queue[s].num-sum[0];
for(int i=2;i+A-1<=N;i++)
{
if(i+B-1<=N)
PUSH(sum[i+B-1],i+B-1);
while(queue[s].pos<i+A-1)
s++;
if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1];
}
printf("%I64d\n",ans);
}
int main()
{
// init();
int T;
cin>>T;
while(T--)
{
input();
solve();
}
return 0;
}
【单调队列】【3-21个人赛】【problmeB】的更多相关文章
- 单调队列 && 斜率优化dp 专题
首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然. 那么如何对单调队列进行操作呢? 是这样的:对于单调队列而言,队首和 ...
- Buying Feed, 2010 Nov (单调队列优化DP)
约翰开车回家,又准备顺路买点饲料了(咦?为啥要说"又"字?)回家的路程一共有 E 公里,这一路上会经过 K 家商店,第 i 家店里有 Fi 吨饲料,售价为每吨 Ci 元.约翰打算买 ...
- BZOJ 5281--[Usaco2018 Open]Talent Show(分数规划&单调队列&DP)
5281: [Usaco2018 Open]Talent Show Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 79 Solved: 58[Sub ...
- HDOJ 5289 Assignment 单调队列
维护一个递增的和递减的单调队列 Assignment Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Ja ...
- 【贪心/DP/单调队列】【CF1029B】Creating the Contest
Description 给你一个单调不下降的长度为n的序列,请你找出一个最长的子序列,满足找出的子序列中,\(A_i<=A_{i-1}~\times~2\),其中i为下标,A为找出的子序列.对于 ...
- HihoCoder1673 : 01间隔矩阵([Offer收割]编程练习赛41)(单调队列)
描述 给定一个N × M的01矩阵,小Hi希望从中找到一个01间隔的子矩阵,并且子矩阵的面积越大越好. 例如对于 0101010 1000101 0101010 1010101 0101010 在右侧 ...
- 算法复习——单调队列(sliding windows,ssoi)
题目: 题目描述 给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,你只能见到窗口的 K 个整数,每次窗体向右移动一位,如下表:
- 洛谷P2569 [SCOI2010]股票交易(单调队列)
传送门 惭愧……这种题目都没看出来…… 首先,我们用$dp[i][j]$表示在第$i$天,手上有$j$股时的最大收益 第一,我们可以直接买股票,即$dp[i][j]=-j*AP_i$,这个直接计算即可 ...
- 洛谷P2219 [HAOI2007]修筑绿化带(单调队列)
传送门 啧……明明以前做到过这种类型的题结果全忘了…… 这种矩阵的,一般都是先枚举行,然后对列进行一遍单调队列,搞出右下角在每一行中合法位置时的最小权值 再枚举列,对行做一遍单调队列,用之前搞出来的最 ...
随机推荐
- SSH框架-Caused by: org.hibernate.MappingException: column attribute may not be used together with <column> subelement
昨晚修改了一些表关系,在相关的hbm.xml文件中做了改动,今天早上起来启动tomcat后,发现项目启动不了,控制台报错: 2015-6-14 9:09:42 org.apache.catalina. ...
- 解决 jsp:include 引用文件时出现乱码的问题
阐述问题前,先来看一下下面这张图片左侧iframe中的乱码页面: 这个就是让我纠结好一阵子的乱码截图: 这个乱码页面中是使用了<jsp:include>引用标签后出现了这个问题: 源码截图 ...
- Mplayer ARM平台下交叉编译
下载MPlayer http://www.mplayerhq.hu/design7/dload.html 编译环境 系统 : ubuntu 11.04 交叉编译器版本 : Sourcery G++ L ...
- HNOI2004 宠物收养所 解题报告
首先读完这题第一印象,是个裸题,很高兴.其次在打完代码之后,第二印象,很恶心,Treap的代码太长了,我今天下午敲了三遍,手都麻了. 废话不多说,正题.其实这个题不难,有几个点是很好的,首先,他的a值 ...
- Floyd算法(弗洛伊德算法)
算法描述: Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法.从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按 ...
- Java Calendar获取年、月、日、时间
Java Calendar获取年.月.日.时间 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00" ...
- 层次节点——NODE节点
1.html <!DOCTYPE html> <html> <head lang="en"> <meta charset="UT ...
- 前端利器,如何使用fiddle拦截在线css进行先下调试
fiddle的功能相当的强悍,用户也非常广,不过今天我就教大家用fiddle进行前端调试. 首先下载软件fiddle,点击对应的版本下载安装. 安装成功后打开看到右侧的导航栏: 点击AutoRespo ...
- 背包问题--nyoj题目106
背包问题 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w< ...
- 【python】bytearray和string之间转换,用在需要处理二进制文件和数据流上
最近在用python搞串口工具,串口的数据流基本读写都要靠bytearray,而我们从pyqt的串口得到的数据都是string格式,那么我们就必须考虑到如何对这两种数据进行转换了,才能正确的对数据收发 ...