(1)POJ1050-经典最大子段和问题

POJ1050
题目: 求给定矩阵的最大子矩阵和,n≤100n≤100n≤100
解题思路: 由于n非常小,完全可以O(n3)O(n^3)O(n3) 来做。枚举矩阵的上下界,处理出当前上下界下,每一列的和,按照经典思路:扫描每一列的和,不断加入子段,当子段和变为负数时,将当前的整个子段清空,再重新加入,不断更新答案。
ac代码:

#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <climits>
using namespace std;
typedef long long ll;
const int maxn = 110;
int a[maxn][maxn], c[maxn], s[maxn];
int n, ans = INT_MIN;
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d", &n);for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)scanf("%d", &a[i][j]);for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++)//枚举子矩阵的起末行号,并求出当前i~j行内的列值{memset(c, 0, sizeof(c));memset(s, 0, sizeof(s));for(int k = 1; k <= n; k++)for(int p = i; p <= j; p++)c[k]+=a[p][k];//当子段和变为负数时清空,否则继续加入for(int k = 1; k <= n; k++){s[k] = s[k-1]>0 ? s[k-1]+c[k] : c[k];ans = max(ans, s[k]);}}}printf("%d\n", ans);return 0;
}

(2)POJ2018-长度不小于F的最大子段和

POJ2018
题目: N(1≤N≤1e5)N(1≤N≤1e5)N(1≤N≤1e5)个农场,每个农场有cowscowscows头牛,选择几个连续的一些农场,满足农场数≥F≥F≥F,且这些农场的牛的平均值最大,求最大值。
解题思路: 二分答案。子段和可以利用前缀和转化为:
max⁡i−j≥F{Aj+1+Aj+2+...+Ai}=max⁡F≤i≤n{sumi−min⁡0≤j≤i−F{sumj}}\max \limits_{i-j≥F}\{A_{j+1}+A_{j+2}+...+A_i\}=\max\limits_{F≤i≤n}\{sum_i-\min\limits_{0≤j≤i-F}\{sum_j\}\}i−j≥Fmax​{Aj+1​+Aj+2​+...+Ai​}=F≤i≤nmax​{sumi​−0≤j≤i−Fmin​{sumj​}}
随着i的增加,j的取值范围每次只增加1,相当于min⁡{sumj}\min\{sum_j\}min{sumj​}每次只会加入一个新的值,所以可以在O(n)O(n)O(n)内处理出子段长度不小于F的最大子段和。
若当前二分答案为xxx,由∑子段和长度L=x\frac{\sum子段和}{长度L}=x长度L∑子段和​=x得∑子段和−长度L∗x=p=0\sum子段和-长度L*x=p=0∑子段和−长度L∗x=p=0,(相当于把每个cows−xcows-xcows−x再求最大子段和)。若p>=0p>=0p>=0则可继续扩大答案,否则缩小答案。
ac代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
const double eps = 1e-5;
int n, f;//至少包含f个fields
double a[maxn], sum[maxn], b[maxn];
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d %d", &n, &f);for(int i = 1; i <= n; i++)scanf("%lf", &a[i]);double l = 0, r = 1e6;while(r-l>eps){double mid = (l+r)/2;for(int i = 1; i <= n; i++){b[i] = a[i]-mid;sum[i] = sum[i-1]+b[i];}double MAX = -1e10;//长度>=f的最大连续子段和double MIN = 1e10;for(int i = f; i <= n; i++){MIN = min(MIN, sum[i-f]);MAX = max(MAX, sum[i]-MIN);}if(MAX>=0) l = mid;else r = mid;}printf("%d\n", (int)(r*1000));return 0;
}

(3)HDOJ6638-线段树维护最大子段和

HDOJ6638
题目: 给定nnn个点的坐标(x,y)(x,y)(x,y)和权值www,求最大子矩阵权值和。−1e9≤x,y,w≤1e9,∑n≤10000-1e9≤x,y,w≤1e9,\sum{n}≤10000−1e9≤x,y,w≤1e9,∑n≤10000。
解题思路: nnn比较大,不能O(n3)O(n^3)O(n3)暴力枚举了,需要将二维转为一维,O(n2logn)来解决。O(n^2logn)来解决。O(n2logn)来解决。 将所有yyy离散化,点的yyy值修改为rankyrankyranky,再将所有点按照xxx从小到大排序,这样处理出来的点的顺序如下:

先枚举起点,以A为起点建线段树,当在线段树上插入完{A,B,C}后查询线段树上当前区间的最大子段和,当插入完{A,B,C,D,E,F}{A,B,C,D,E,F.G,H,I}时分别查询答案;同理以D为起点建立线段树,当插入完{D,E,F}{D,E,F,G,H,I}时分别查询查询答案;以G为起点建立线段树,插入完{G,H,I}时查询答案。
ac代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3+10;
struct point{int x, y, w;point(){};friend bool operator < (point a, point b){return a.x==b.x ? a.y<b.y : a.x<b.x;}
}p[maxn];
struct node{int l, r;ll mx, max_pre, max_suf, sum;//区间最大子段和,最大前缀和,最大后缀和,总和
}tree[maxn<<2];
int y[maxn];
int t, n;
void build(int id, int l, int r)
{tree[id].l = l; tree[id].r = r;tree[id].sum=tree[id].max_pre=tree[id].max_suf=tree[id].mx=0;if(l==r) return ;int mid = (l+r)>>1;build(id<<1, l, mid);build(id<<1|1, mid+1, r);
}
void push_up(int id)
{tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;tree[id].max_pre = max(tree[id<<1].max_pre, tree[id<<1].sum+tree[id<<1|1].max_pre);tree[id].max_suf = max(tree[id<<1|1].max_suf, tree[id<<1|1].sum+tree[id<<1].max_suf);//最大子段和mx=max(左区间mx, 右区间mx, 左区间最大后缀和+右区间最大前缀和)tree[id].mx = max(max(tree[id<<1].mx, tree[id<<1|1].mx), tree[id<<1].max_suf+tree[id<<1|1].max_pre);
}
void insert(int id, int k, int w)//从id=1开始给y排名为k的叶子节点+w
{if(tree[id].l==tree[id].r){tree[id].sum=tree[id].max_pre=tree[id].max_suf=tree[id].mx=tree[id].mx+w;return ;}int mid = (tree[id].l+tree[id].r)>>1;if(k<=mid) insert(id<<1, k, w);else insert(id<<1|1, k, w);push_up(id);
}int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d", &t);while(t--){ll ans = LONG_LONG_MIN;scanf("%d", &n);for(int i = 1; i <= n; i++){scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].w);y[i] = p[i].y;}sort(y+1, y+1+n);int num = unique(y+1, y+1+n)-(y+1);for(int i = 1; i <= n; i++)p[i].y=lower_bound(y+1, y+1+num, p[i].y)-y;sort(p+1, p+1+n);//y离散化后,按x从小到大排序for(int i = 1; i <= n; i++){if(i!=1 && p[i].x==p[i-1].x) continue;//不建重复的树build(1, 1, num);for(int j = i; j <= n; j++){if(j!=i && p[j].x!=p[j-1].x) ans = max(ans, tree[1].mx);insert(1, p[j].y, p[j].w);}ans = max(ans, tree[1].mx);}printf("%lld\n", ans);}return 0;
}

(4)长度不小于m的最大连续子序列和

传送门
题目: 给定长度为n的整数序列,找到最大的长度不超过m的连续子序列和,n,m≤3e5
解题思路: 固定子序列[j, i]的右端点i,那么j∈[i−m+1,i]j\in[i-m+1,i]j∈[i−m+1,i]且子序列[j,i]内的和利用前缀和可以转化为sum[i]−sum[j−1]sum[i]-sum[j-1]sum[i]−sum[j−1]。i一定,sum[j-1]最小,连续子序列和最大。令J=j-1,J∈[i−m,i−1]J\in[i-m, i-1]J∈[i−m,i−1]。在枚举i的过程中,J的区间每次右移一位,每次都在相应的区d间内找最小值,这样这道题就转化成了洛谷P1886滑动窗口那道题,用单调队列来做,队头存最小值。
注意队列里要先放一个0,因为i是先取到最小值(最小值是在队列非空的时候才取得到)后再存入。
ac代码:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 3e5+10;
deque<int> q;//队头最大/小值
int n, m;
ll sum[maxn];
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d %d", &n, &m);for(int i = 1; i <= n; i++) scanf("%lld", &sum[i]), sum[i]+=sum[i-1];ll ans = LLONG_MIN;//在[i-m, i-1]中找最小的sum[J]q.push_back(0);for(int i = 1; i <= n; i++){while(!q.empty() && sum[q.back()]>sum[i]) q.pop_back();while(!q.empty() && q.front()<i-m) q.pop_front();if(!q.empty()) ans = max(ans, sum[i]-sum[q.front()]);q.push_back(i);}printf("%lld\n", ans);return 0;
}

【POJ1050+POJ2018+HDOJ6638+牛客1006D】最大子段和问题相关推荐

  1. 牛客练习赛40 A.小D的剧场

    链接:https://ac.nowcoder.com/acm/contest/369/A?&headNav=acm 来源:牛客网 题目描述 "我明白." 作为这命运剧场永远 ...

  2. 【牛客 - 369A】小D的剧场(线性dp)

    题干: 链接:https://ac.nowcoder.com/acm/contest/369/A 来源:牛客网 题目描述 "我明白." 作为这命运剧场永远的观众,小D一直注视着这片 ...

  3. 洛谷or牛客数据结构+算法

    栈思想:先进后出 tips:栈里能放下标就放下标 (牛客)小c的计事本(直接用stack可以简化代码,且不会被自己绕晕,当时没意识到) (牛客)吐泡泡(没意识到用栈),(牛客)好串 1.后缀表达式(栈 ...

  4. 2022牛客暑期多校训练营训练日志

    2022牛客暑期多校训练营1 G - Lexicographical Maximum 签到题. A - Villages: Landlines 简化题意:给你 nnn 条线段,问你把这些线段铺到数轴上 ...

  5. 2020牛客寒假算法基础集训营4

    链接:link 来源:牛客网 A 欧几里得 题目描述 现在,如果已知 g c d ( a , b ) gcd(a,b) gcd(a,b) 共递归了 n n n次,求所有可能的 a , b a,b a, ...

  6. [C++] 牛客网:合并两个有序的数组

    主要是体验一下牛客网里的核心代码模式到底是怎么弄的..还有C++这个东西平常用的太少了,试一试. 以外的还体验到了sort()函数的使用. 来源:牛客网 题目链接:合并两个有序的数组 知识点:数组.双 ...

  7. 牛客~~打篮球~~~模拟水题

    链接:https://www.nowcoder.com/acm/contest/118/D 来源:牛客网 题目描述 1, 2, 3在打篮球, 可是二打一总是不公平的, 于是他们决定一对一,另一个人在边 ...

  8. 字节跳动java笔试题目_牛客网--字节跳动面试题--特征提取

    牛客网--字节跳动面试题--特征提取 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 来源 链接:特征提取 来源:牛客网 题目 ...

  9. 2019年牛客多校第1场 赛后总结

    A题 :Equivalent Prefixes  题意:就是给你两个有n个不同数的串,然后保证1-p区间内任选一个区间,使得区间中最小值的下标相同,找到最大的p值  思路:我的思路是设置两个单调栈,然 ...

  10. 牛客小白月赛5-F题: 圆(circle)

    题目链接:https://www.nowcoder.com/acm/contest/135/F 题解作者:Stump 题解链接:https://www.nowcoder.com/discuss/878 ...

最新文章

  1. LeetCode简单题之交替位二进制数
  2. 闪耀澳网 跨界新品泸州老窖国窖1573澳网冠军版发布
  3. android sdk国内快速更新下载
  4. 最大连续子序列乘积(DP)
  5. 重磅!公开基于“内心对话”的EEG脑机接口数据集,助力语音意念控制研究
  6. Springboot使用JPA框架对数据库实现增删改查(附详细代码)
  7. datepicker 颜色 android,Android修改DatePicker字體顏色及分割線顏色
  8. 用lemon测交互题
  9. Python控制鼠标和键盘-PyAutoGUI用法详解
  10. 中国小吃文化名城掀“味蕾风暴”:故事抱团 欲刮全球
  11. LogMiner Tool
  12. 初识ABP vNext(11):聚合根、仓储、领域服务、应用服务、Blob储存
  13. WebSocket In ASP.NET Core
  14. 2021年河南省高考成绩位次查询,2021年河南高考分数一分一段位次表,河南高考个人成绩排名查询方法...
  15. 南京信息工程大学c语言期末答案,南京信息工程大学试卷2011-2012(2)c语言程序设计试卷答案(文科)-a...
  16. 值不值得入手_看好三阳的小拉力,但不知道值不值得入手?
  17. JavaScript:如何将消息打印到错误控制台?
  18. 2021全球程序员收入报告出炉!
  19. Schizophrenia Bulletin:未用药精神分裂症患者的纹状体多巴胺与奖赏预测误差信号
  20. 爱国者p8880e java_口袋里的电脑 爱国者P8880E MID评测

热门文章

  1. office2010的安装和卸载
  2. zlib再windows下的编译
  3. mysql sql security_MySQL笔记-definer与SQL SECURITY
  4. matlab输入一个正的实数x,VB程序题:用InputBox 输入一个正实数,用Pring方法在一行上显示出它的平方和平方根、立方和立方根,每个数保留三位小数,其间有间隔。...
  5. 前端页面因为过滤器出现路径不正确,css效果不展示
  6. zabbix2.4监控mysql_Zabbix 2.4.5自带MySQL监控的配置使用教程
  7. 图标圆角角度_教你在 iOS 和 macOS 上获取 App 图标
  8. svm分类器_用人话讲明白支持向量机SVM(上)
  9. 【转】正则表达式–零宽断言详解
  10. 如何通过 Redis 实现分布式锁