BZOJ2086 POI2010 Blocks-程序员宅基地

技术标签: 单调栈  POI 2010  POI  


POI2010 题解整理

Description

给出 N 个正整数 a[1N] ,再给出一个正整数 k ,现在可以进行如下操作:每次选择一个大于 k 的正整数 ai ,将 ai -1,选择 ai1 ai+1 中的一个+1。

经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数都不小于 k 。总共给出 M 次询问,每次询问给出的 k 不同,你需要分别回答。

Input

  • 第一行两个正整数 N(N106) M(M50)

    • 第二行 N 个正整数,第 i 个正整数表示 ai(ai109)
    • 第三行 M 个正整数,第 i 个正整数表示第i次询问的 k(k109)

Output

  • 共一行,输出M个正整数,第i个数表示第i次询问的答案。

Sample Input

5 6
1 2 1 1 5
1 2 3 4 5 6

Sample Output

5 5 2 1 1 0


Solution

这道题目和牛宫一题非常像。

首先要得到这条式子: ans=max{ RL:Ri=1aiLj=1aj(RL)k}

暂且设 sumi=ij=1ajik ,则对于每一个 R ,要找 [0,R1] 内最小的 L ,并且满足 sumRsumL

有一个性质:

  • 对于两个点 k,j(k<j) ,如果 sumksumj ,那么这个j是一定用不到的。

所以我们可以维护一个单调栈,当满足 sumstk[top]>sumi 的时候才将i放入。那么我们就会发现这个单调栈呈现这样一种情况:下标在不断增大,但是 sumpos 在不断减小。于是我们找到栈中最小的 pos ,且满足 sumpossumi 即可。

#include<bits/stdc++.h>
#define M 1000005
using namespace std;
long long sum[M];
inline void Rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>47);
}
int stk[M],top=0;
int main(){
    int n,m;Rd(n),Rd(m);
    for(int i=1,x;i<=n;i++){
        Rd(x);sum[i]=sum[i-1]+x;
    }
    for(int _=1;_<=m;++_){
        int k;Rd(k);
        top=0;
        int ans=0;
        stk[++top]=0;
        for(int i=1;i<=n;i++){
            if(sum[stk[top]]-1LL*stk[top]*k>sum[i]-1LL*i*k)stk[++top]=i;
            else{
                int L=1,R=top,res=-1;
                while(L<=R){
                    int mid=L+R>>1;
                    if(sum[stk[mid]]-1LL*stk[mid]*k<=sum[i]-1LL*i*k){
                        R=mid-1;
                        res=mid;
                    }else L=mid+1;
                }
                if(~res)ans=max(ans,i-stk[res]);
            }
        }
        printf("%d%c",ans,_==m?'\n':' ');
    }
}

(16/11/17更新)为了将二分的 O(logn) 复杂度转化为线性复杂度,我们需要回到最开始的模拟中——我们枚举当前的右端点,然后将左端点的位置不断向左滑动。由于我们不能确定,在当前的 sumL>sumR 的前方,是否有比 sumL 更小的值可以转移,所以单次询问我们暴力的复杂度为 O(N2)

但是对于每个位置,前面最小的值可以利用动态规划在 O(n) 时间内计算。于是我们上述缺陷的判断就可以被填补,我们在滑动L的时候,只要判断前面最小的值是否 sumR 即可。不能滑动时,我们不必撤销当前的最优解并且下一轮从头滑动L,我们保持这个区间向右滑动即可。这样此处均摊的复杂度仍为 O(n)

综上,最后总复杂度为 O(nm)

#include<bits/stdc++.h>
#define M 1000005
using namespace std;
long long sum[M];
inline void Rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>47);
}
int Min[M];
int main(){
    int n,m;Rd(n),Rd(m);
    for(int i=1,x;i<=n;i++){
        Rd(x);
        sum[i]=sum[i-1]+x;  
    }
    for(int _=1;_<=m;++_){
        int k;Rd(k);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(sum[Min[i-1]]-1ll*Min[i-1]*k<=sum[i]-1ll*i*k)Min[i]=Min[i-1];
            else Min[i]=i;
        for(int i=1;i<=n;i++)
            while(i-ans>=0&&sum[Min[i-ans]]-1ll*Min[i-ans]*k<=sum[i]-1ll*i*k)ans++;
        printf("%d%c",ans-1,_==m?'\n':' ');
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Kanosword/article/details/52724567

智能推荐

查看表大小和查看表空间的大小_数据库表空间大小查看-程序员宅基地

有两种含义的表大小。一种是分配给一个表的物理空间数量,而不管空间是否被使用。可以这样查询获得字节数:select segment_name, bytes from user_segments where segment_type = 'TABLE'; 或者Select Segment_Name,Sum(bytes)/1024/1024 From User_Extents G_数据库表空间大小查看

EGL简介_egldisplay-程序员宅基地

OpenGL实现跨平台的功能,在不同的操作系统上需要不同的类似适配层的内容,比如在Windows操作系统上需要WGL。同样的,OpenGL ES是一个平台中立的图形库,在它能够工作前,需要与一个实际的窗口关联起来,但是,与OpenGL不一样的是,OpenGL是每个窗口系统需要一个与之对应的适配层,Windows需要WGL,X-Window需要xgl,Mac OS需要agl。而OpenGL ES_egldisplay

卷积 | 深度可分离卷积、分组卷积、空洞卷积、转置卷积(反卷积)_空洞卷积 反卷积-程序员宅基地

参考: https://zhuanlan.zhihu.com/p/28749411 https://zhuanlan.zhihu.com/p/28186857 https://blog.yani.io/filter-group-tutorial/ https://www.zhihu.com/question/54149221 http://blog.csdn.net/guvcolie/articl..._空洞卷积 反卷积

【Android开发】高级组件-自动完成文本框-程序员宅基地

自动完成文本框(AutoCompleteTextView),用于实现允许用户输入一定字符后,显示一个下拉菜单,供用户从中选择,当用户选择某个选项之后,按用户选择自动填写该文本框。语法格式:属性列表>AutoCompleteTextView组件继承EditText,所以它支持EditText组件提供的属性,同时,该组件还有以下属性:android:completion

GT Transceiver的复位与初始化(3)TX初始化和复位流程_pma和pcs能否单独复位-程序员宅基地

GTX/GTH收发器TX使用一个复位状态机来控制复位过程。GTX/GTH收发器TX被划分为两个复位区域,TX PMA和TX PCS。_pma和pcs能否单独复位

Shut Down!BY WangKe.Automation.WUST.2012.10,based on VC.-程序员宅基地

//*******************************************************************************************//************************Shut Down! BY WangKe.Automation.WUST.2012.10***********************//********

随便推点

解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.--程序员宅基地

bug:今天做项目的时候遇到了这样一个崩溃信息:解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.-2017-06-22 16:45:42.229 ViewTest[2638:c07] *** Terminating app due to un...

javascript中Array的slice和splice方法的比较_es6 slice和splice-程序员宅基地

slice(start,end):返回数组中下标从start到end之间的一段数组元素组成的新的数组,并不会对原数组产生任何影响。(就像是String中的substring方法一样)。splice(start,count):将数组从下标为start的位置开始删除count个数组元素,立即更新数组的状态(即是使原数组发生了改变)。_es6 slice和splice

内外网隔离 双网隔离DoraOS云终端双桌面云办公应用_双网隔离软件-程序员宅基地

目前内外网使用物理隔离的方法:1 使用双主机实现隔离,这样不仅增加采购成本,而且维护麻烦,占用更多的办公空间。2 使用单主机,硬盘隔离卡切换不同桌面。这种方式切换桌面需要重启,切换速度慢,而且不稳定,切换频繁容易引起蓝屏,死机等问题,影响工作效率。jyos系统云终端实现双网隔离的优势:使用jyos系统的云终端可以使用双屏实现同时连接内网和外网,共用一套键盘鼠标,键盘鼠标..._双网隔离软件

关于toLua封装和解析ProtoBuffer-程序员宅基地

@关于toLua封装和解析ProtoBuffer封装ProtoBuffer发送给服务器local serverId = 127.0.0.1;function Net.WrapAndSendMessageToServer(msgId,msgBody)local msg = msgBody:SerializeToString();local buffer = ByteBuffer.New()...

菜鸟学web.py--拾遗-程序员宅基地

1.所有的模板只能共享一个HTML标签,如的,在其他地方不能有任何关于HTML信息之类的东西,如头文件,,之类的,否则出错,其它模板文件也一样2.模板注释一定要写在末尾,至少要在def with后面,否则会有莫名其妙的错误!不管什么情况,def with必须在第一行!

ng2 体验报告、总结-程序员宅基地

当然,现在 angular 最新的版本已经出到 5.0 了,现在才来说 ng2 有点老套了,只是最近忽然的从 react 的项目组转到了做 angular v2 (ng2) 的项目组,同时对谷歌和微软的”孩子”也比较感兴趣,所以还是有必要好好学习一下的。 上手了一阵子,大概摸清了 ng2 的套路,其实在此之前,对于习惯了 React、 Vue 开发模式的我来说,对于 ng2 是有一定的误解