[POI2015]Wilcze doły

题目大意:

给定一个长度为\(n(n\le2\times10^6)\)的数列\(A(1\le A_i\le10^9)\),可以从中选取不超过\(d\)个连续数字变成\(0\),求一个最长的子串使得这段数的和不超过\(p\)。

思路1:

显然,将\(d\)个修改的机会用完一定最优,答案至少为\(d\)。

二分答案\(k\),\(O(n)\)枚举端点,若区间和-区间最大的长度为\(d\)的子段和\(\le p\),则答案至少为\(k\)。

而“区间最大的长度为\(d\)的子段和”可以用稀疏表维护,时空复杂度均为\(\mathcal O(n\log n)\)。

然而这题空间限制128MB,还要开int64,会MLE,要是空间开到512MB也能过了。

源代码1:

#include<cstdio>
#include<cctype>
#include<algorithm>
typedef long long int64;
inline int64 getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int64 x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=2e6+1,logN=21;
int n,a[N],d;
int64 p,sum[N],max[N][logN];
inline int lg2(const float &x) {
return ((unsigned&)x>>23&255)-127;
}
inline bool check(const int &k) {
for(register int i=k;i<=n;i++) {
const int l=lg2(k-d+1);
if(sum[i]-sum[i-k]-std::max(max[i-k+d][l],max[i-(1<<l)+1][l])<=p) return true;
}
return false;
}
int main() {
n=getint(),p=getint(),d=getint();
for(register int i=1;i<=n;i++) {
a[i]=getint();
sum[i]=sum[i-1]+a[i];
if(i>=d) max[i][0]=sum[i]-sum[i-d];
}
for(register int j=1;j<=lg2(n-d+1);j++) {
for(register int i=d;i<=n;i++) {
max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]);
}
}
int l=d+1,r=n;
while(l<=r) {
const int mid=(l+r)>>1;
if(check(mid)) {
l=mid+1;
} else {
r=mid-1;
}
}
printf("%d\n",l-1);
return 0;
}

思路2:

不难发现当右端点单调递增时,能选取的最大的左端点具有单调性。

而“区间最大的长度为\(d\)的子段和”可以用单调队列维护。

时空复杂度\(\mathcal O(n)\)。

源代码2:

#include<queue>
#include<cstdio>
#include<cctype>
typedef long long int64;
inline int64 getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int64 x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=2e6+1;
std::deque<int> q;
int a[N];
int64 sum[N],tmp[N];
int main() {
const int n=getint();
const int64 p=getint();
const int d=getint();
for(register int i=1;i<=n;i++) {
a[i]=getint();
sum[i]=sum[i-1]+a[i];
if(i>=d) tmp[i]=sum[i]-sum[i-d];
}
int ans=d;
q.push_back(d);
for(register int i=d+1,last=0;i<=n;i++) {
while(!q.empty()&&q.front()-d<last) q.pop_front();
while(!q.empty()&&tmp[q.back()]<=tmp[i]) q.pop_back();
q.push_back(i);
while(!q.empty()&&sum[i]-sum[last]-tmp[q.front()]>p) {
last++;
if(!q.empty()&&q.front()-d<last) q.pop_front();
}
ans=std::max(ans,i-last);
}
printf("%d\n",ans);
return 0;
}

[POI2015]Wilcze doły的更多相关文章

  1. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

  2. 【BZOJ4385】[POI2015]Wilcze doły 单调栈+双指针法

    [BZOJ4385][POI2015]Wilcze doły Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段 ...

  3. BZOJ4385 : [POI2015]Wilcze doły

    求出前缀和$s$,设$f[i]=s[i+d-1]-s[i-1]$. 从左到右枚举的右端点$i$,左端点$j$满足单调性,若$s[i]-s[j-1]-\max(区间内最大的f)\leq p$,则可行. ...

  4. BZOJ4385[POI2015]Wilcze doły——单调队列+双指针

    题目描述 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得该区间内所有数字之和不超过p. 输入 第一行包含三个整数n,p ...

  5. bzoj 4385: [POI2015]Wilcze doły【单调栈】

    对于每个i,以它为左端点的最优右端点一定是单增的,所以用单调栈维护 具体的,单调栈里放的是和单调的长为d的子段,然后枚举右端点,如果这段的和-当前长为d子段最大的和大于p的话,左端点右移同时注意单调栈 ...

  6. 【bzoj4385】[POI2015]Wilcze doły

    单调队列扫描,记录当前区间长度为d的一段的和的最大值,和当前区间和. #include<algorithm> #include<iostream> #include<cs ...

  7. [bzoj4385][POI2015]Wilcze doły_单调队列

    Wilcze doły bzoj-4385 POI-2015 题目大意:给定一个n个数的序列,可以将连续的长度不超过d的区间内所有数变成0,求最长的一段区间,使得区间和不超过p. 注释:$1\le n ...

  8. P3594 [POI2015]WIL-Wilcze doły

    P3594 [POI2015]WIL-Wilcze doły 题目描述 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得 ...

  9. Luogu 3594 [POI2015]WIL-Wilcze doły

    简单题. 考虑没有修改数字的条件的限制,我们直接用双指针扫描就可以计算出答案了. 然后考虑加入修改数字的条件,只要用单调队列维护出当前两个指针表示的区间中长度为$d$的一段区间的最大值,用总和减掉这个 ...

随机推荐

  1. Java编程思想 4th 第1章 对象导论

    所有编程语言都提供抽象机制. 面向对象编程似乎是一种很好的编程思想和方式,面向对象编程中的对象简洁描述是:对象具有状态.行为和标识.状态指的是数据存储,存储的数据能反应状态:行为指的是方法,方法表示对 ...

  2. springboot集成mybatis环境搭建以及实现快速开发微服务商品模块基本的增删改查!

    之前学习了springboot和mybatis3的一些新特性,初步体会了springboot的强大(真的好快,,,,,),最近趁着复习,参考着以前学习的教程,动手写了一个springboot实战的小例 ...

  3. Linux configure关于交叉编译的参数设置【转】

    转自:http://blog.csdn.net/darennet/article/details/9003005 configure的参数众多,一般包括如下 --srcdir=DIR 这个选项对安装没 ...

  4. linux中core dump开启使用教程【转】

    转自:http://www.111cn.net/sys/linux/67291.htm 一.什么是coredump 我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各 ...

  5. 在c++中实现反射的初步想法

    最近在思考如何在c++中实现反射.事情的起因是这样的:我们服务器是用c++开发的,如果需要写一些测试用的GM指令的话,需要编写完GM代码后重新编译并且重启进程,工序繁琐且比较耗时.因此就有了想用脚本( ...

  6. RESTful Web 服务:教程

    RESTful Web 服务:教程   随着 REST 成为大多数 Web 和 Mobile 应用的默认选择,势必要对它的基本原理有所了解. 在它提出十多年后的今天,REST 已经成为最重要的 Web ...

  7. C# 浅谈 接口(Interface)的作用

    继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的 1.接口用于描述一组类的公共方法/公共属性. 它不实现任何的方法 ...

  8. c++字节数组转换为整型

    http://bbs.csdn.net/topics/360132089 BYTE data[4]={0x00,0x00,0xe6,0x00};//第一句UINT a11=*(UINT*)data;/ ...

  9. 一文看懂python主要应用领域或应用场景

    Python简介 Python(英国发音:/ˈpaɪθən/美国发音:/ˈpaɪθɑːn/),是一种面向对象的解释型计算机程序设计语言,由荷兰人GuidovanRossum于1989年发明,第一个公开 ...

  10. 删除git库中untracked files(未监控)的文件

    https://blog.csdn.net/ronnyjiang/article/details/53507306 在编译git库拉下来的代码时,往往会产生一些中间文件,这些文件我们根本不需要,尤其是 ...