这题我有闪过是用单调队列优化的想法,也想过有左右两边各烧一遍。 但是不敢确定,搜了题解,发现真的是用单调队列,然后写了好久,调了好久下标应该怎么变化才过的。

dp[i][j] 表示走到第i行,第j个竖线的最大价值。

dp[i][j] = max(dp[i-1][k]+pre[i][j-1]-pre[i][k-1]);  从左往右

dp[i][j] = max(dp[i][j],dp[i-1][k]+suf[i][j]-suf[i][k]); 从右往左

 #pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
const int INF = << ;
typedef __int64 LL;
/*
dp[i][j]表示走到第i个横线,第j个竖线的最大值
dp[i][j] = max(dp[i-1][k] + sum[j-1] - sum[k-1])
单调队列优化维护队首最大值,
*/ int q[], head, tail;
int dp[][];
int a[][];
int b[][];
int pre[][], suf[][];
int sum1[][];
int sum2[][];
int main()
{
int n, m, k; while (scanf("%d%d%d", &n, &m, &k),n+m+k)
{
memset(dp, , sizeof(dp));
memset(pre, , sizeof(pre));
memset(suf, , sizeof(suf));
memset(sum1, , sizeof(sum1));
memset(sum2, , sizeof(sum2));
n++;
for (int i = ;i <= n;++i)
{
for (int j = ;j <= m;++j)
{
scanf("%d", &a[i][j]);
pre[i][j] = pre[i][j - ] + a[i][j];
suf[i][j] = a[i][j];
}
for (int j = m;j >= ;--j)
suf[i][j] += suf[i][j + ]; }
for (int i = ;i <= n;++i)
{
for (int j = ;j <= m;++j)
{
scanf("%d", &b[i][j]);
sum1[i][j] = b[i][j];
sum2[i][j] = sum2[i][j - ] + b[i][j];
}
for (int j = m;j >= ;--j)
sum1[i][j] += sum1[i][j + ];
}
for (int i = n;i >= ;--i)
{
head = tail = ;
for (int j = ;j <= m + ;++j)
{
while (head < tail && dp[i + ][j] - pre[i][j - ] >= dp[i + ][q[tail - ]] - pre[i][q[tail - ] - ])
tail--;
q[tail++] = j;
while (head<tail && sum2[i][j-] - sum2[i][q[head]-]>k)
head++;
dp[i][j] = dp[i + ][q[head]] + pre[i][j - ] - pre[i][q[head]-];
}
head = tail = ; for (int j = m+;j >= ;--j)
{
while (head < tail&&dp[i + ][j] - suf[i][j ] >= dp[i + ][q[tail - ]] - suf[i][q[tail - ] ])
tail--;
q[tail++] = j;
while (head<tail&&sum1[i][j] - sum1[i][q[head]]>k)
head++;
dp[i][j] =std::max(dp[i][j], dp[i + ][q[head]] + suf[i][j] - suf[i][q[head]]);
}
}
int ans = ;
for (int j = ;j <= m + ;++j)
ans = std::max(ans, dp[][j]);
printf("%d\n", ans);
}
return ;
}

最新文章

  1. hdu1695 GCD(莫比乌斯反演)
  2. Windows如何修改MySQL用户root密码
  3. IE11之F12 Developer Tools--调试器(Debugger)
  4. POJ2823 Sliding Window(单调队列)
  5. open和fopen的区别:
  6. SQL语句使用时间和日期的函数
  7. 深入理解java虚拟机之java内存区域
  8. MongoDB的数据备份与恢复
  9. LNMP下Nginx 中文文件名或目录404无法访问的解决方法
  10. 在property里面设置版本号可灵活引用
  11. .Net拾忆:Asp.net请求管道
  12. 黄聪:清理微信浏览网站的缓存,Cookie
  13. Structs复习 Result第二部分
  14. BZOJ5287 HNOI2018毒瘤(虚树+树形dp)
  15. codeM编程大赛E题 (暴力+字符串匹配(kmp))
  16. Windows下安装Oracle12C(二)
  17. 使用Apache POI处理excel公式不更新的解决办法
  18. python 加密方式(MD5&amp;sha&amp;hashlib)
  19. linux 用户/用户组添加修改删除(ubuntu/centos)
  20. bzoj1050[HAOI2006]旅行comf(枚举+贪心+并查集)

热门文章

  1. 什么是防盗链设置中的空Referer
  2. VI01增强问题
  3. 链栈之C++实现
  4. 线程同步辅助类——Exchanger
  5. Mac必备软件推荐
  6. 高级Bash脚本编程指南(27):文本处理命令(三)
  7. 改动Oracle GoldenGate(ogg)各个进程的读检查点和写检查点
  8. HDU 1535 Invitation Cards (POJ 1511)
  9. [初探iOS开发]storyboard的使用
  10. 无向图的最短路径算法JAVA实现(转)