再谈 前缀和,差分,离散化

【日报】差分与前缀和,但是加上了一些拓展 - 白色过膝袜 - 洛谷博客 (luogu.com.cn)

预计学习时间: 一天

因为发现有好多题目都需要利用前缀和还有差分来进行优化,所以要花一天的时间把这种基础算法学完.

复制代码
//前缀和: //二维前缀和: //1-1 激光炸弹: https://www.luogu.com.cn/problem/P2280 //这里只需要建立一个二维前缀和,然后遍历每一个框架就可以 //不能枚举所有的点,因为点实在是太多了 #include<bits/stdc++.h> #define ll long long using namespace std; const int N=5010; int n,r,s[N][N],res; int main() { std::ios::sync_with_stdio(false); cin>>n>>r; r=min(r,5002); for(int i=0;i<n;i++){ int a,b,c; cin>>a>>b>>c; s[a][b]+=c; //因为如果点在边上的话,是无效的,所以我们的框是要框住比自己小的 //3x3的框就要框2x2的炸弹 } for(int i=1;i<=5002;i++) for(int j=1;j<=5002;j++) s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1]; for(int i=r;i<=5002;i++) for(int j=r;j<=5002;j++) res=max(res,s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r]); cout<<res; return 0; }
复制代码
复制代码
//差分 //增减序列:https://ac.nowcoder.com/acm/contest/999/B #include<bits/stdc++.h> using namespace std; const int N=1e5+10; long long res,ans,c[N],n,a[N]; int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i],c[i]=a[i]-a[i-1]; for(int i=2;i<=n;i++){ if(c[i]>0) res+=c[i];//统计所有的差分正数 else if(c[i]<0) ans-=c[i];//所有的差分负数 //这里讲一下思路: 对于整个差分数列,有正值有负值,那么我们的目标是2-n的序列全变为0 //通过改变某一区间让min(正,负)变为0,剩下的一个让从1开始到n结束来 //因为如果改变当前的c[i]值的话,可以巧妙地发现,知识改变的当前的值,后面的c仍然不变,所以可以随意放心的改 } cout<<min(res,ans)+abs(res-ans)<<endl<<abs(res-ans)+1; return 0; }
复制代码

 

复制代码
//45分代码 #include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,num; long long c[N],a[N],s[N]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i],c[i]=a[i]-a[i-1],s[i]=s[i-1]+a[i]; for(int i=1;i<=m;i++){ int x,y,z; cin>>x>>y>>z; for(int j=y;j<=z;j++) if(a[j]<x) return cout<<-1<<endl<<i,0; c[x]-=z,c[y+1]+=z; for(int i=1;i<=n;i++){ a[i]=a[i-1]+c[i]; if(a[i]<0) return cout<<-1<<endl<<i,0; } } cout<<0; return 0; } //满分ac代码: #include<bits/stdc++.h> using namespace std; const int N=1e6+10; long long c[N],need[N],st[N],ed[N],n,m,res,a[N],p[N]; bool check(int u) { memset(c,0,sizeof c); for(int i=1;i<=u;i++) c[st[i]]+=need[i],c[ed[i]+1]-=need[i]; for(int i=1;i<=n;i++){ p[i]=p[i-1]+c[i]; if(p[i]>a[i]) return 0; } return true; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) cin>>need[i]>>st[i]>>ed[i]; if(check(m)) return cout<<0,0; int l=1,r=m; while(l<r){ int mid=l+r>>1; if(check(mid)) res=mid,l=mid+1; else r=mid; } cout<<-1<<endl<<l; return 0; }
复制代码

 


__EOF__

本文作者Sakurajimamai
本文链接https://www.cnblogs.com/o-Sakurajimamai-o/p/17486625.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   o-Sakurajimamai-o  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
-- --
点击右上角即可分享
微信分享提示