博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2627 修剪草坪[dp][单调队列]
阅读量:6452 次
发布时间:2019-06-23

本文共 1496 字,大约阅读时间需要 4 分钟。

P2627 修剪草坪

给你一个\(n\)个数字的数组,至多连续取\(k\)个数字,求取出的最大和。

预处理了前缀和之后,一维dp很容易想:\(dp[i] = max(dp[j-1] + sum[j+1,i])\)

用前缀和写就是\(dp[i]=max(dp[j-1]+sum[i]-sum[j])\)

把与\(i\)有关的拿出\(max\),就有\(dp[i]=sum[i]+max(dp[j-1]-sum[j])\)

\(j\)能取的是一个固定区间,长度为\(k\),所以直接单调队列维护咯!

维护一个单调递减的队列,队头就是最大值了。

复杂度为\(O(n)\)。太优美了!

代码:

/************************************************************************* @Author: Garen @Created Time : Tue 12 Feb 2019 10:19:25 AM CST @File Name: P2627.cpp @Description: ************************************************************************/#include
#define ll long longconst ll maxn = 100005;ll dp[maxn];ll a[maxn], sum[maxn];ll n, k;std::deque
q;ll d[maxn];ll update(ll i) { d[i] = dp[i - 1] - sum[i]; while(!q.empty() && d[q.back()] < d[i]) q.pop_back(); q.push_back(i); while(!q.empty() && q.front() < i - k) q.pop_front(); return d[q.front()];}int main() { scanf("%lld %lld", &n, &k); for(ll i = 1; i <= n; i++) { scanf("%lld", &a[i]); sum[i] = sum[i - 1] + a[i]; } /* for(ll i = 1; i <= k; i++) dp[i] = sum[i]; for(ll i = k + 1; i <= n; i++) { for(ll j = i - k; j <= i; j++) { dp[i] = std::max(dp[i], dp[j - 1] + sum[i] - sum[j]); } // dp[i] = sum[i] + std::max(dp[j - 1] - sum[j])); } */ q.push_back(0); for(ll i = 1; i <= n; i++) { dp[i] = sum[i] + update(i); } printf("%lld\n", dp[n]); return 0;}

转载于:https://www.cnblogs.com/Garen-Wang/p/10381421.html

你可能感兴趣的文章
linux下单个网卡设置多IP
查看>>
大硬盘在服务器上使用
查看>>
阿里五年晋升三次,这个程序员要聊聊他的选择
查看>>
Linux 开机流程及修复MBR
查看>>
How-to use MySQL-python in Python
查看>>
从用户层面考虑如何做好一款产品
查看>>
MYSQL的limit和offset
查看>>
基于Corosync + LNMP + NFS 服务实现高可用
查看>>
Python 多线程
查看>>
[java理论篇]--JAVA反射机制
查看>>
PostgreSQL的HA(主备切换)
查看>>
安装Office2010/2007出现1935错误解决办法
查看>>
使用rpm包安装配置 LAMP
查看>>
如何利用PS脚本查询和管理硬盘空间
查看>>
AFN获取数据后刷新TableView
查看>>
我的友情链接
查看>>
vsftpd添加新用户
查看>>
Math 单元下的公用函数目录
查看>>
WinAPI: CreatePatternBrush - 建立位图画刷
查看>>
PHP配置文件详解php.ini
查看>>