前缀和与差分
前缀和
*一维
定义:一维前缀和S[i]表示的就是a[1]+a[2]+…+a[i]。
作用:求a[i]~a[j]的和
例如:有一列数字{a},多次询问一个区间[L,R]的和。n,m<=1000000。n
做法很简单,令s[p]=s[p-1]+a[p]=a[1]+a[2]+…+a[p],那么:
a[L]+a[L+1]+…+a[R]=s[R]-s[L-1]
递推式:s[i]=s[i-1]+a[i]
*二维
定义:二维前缀和S[i][j]表示的是所有a[i’][j’](1<=i’<=i, 1<=j’<=j)的和。
作用:假如我们处理出了前缀和S[i][j],给定x1,y1,x2,y2,我们想求一下所有
A[i’][j’](x1<=i’<=x2,y1<=j’<=y2)的和。
ans=S[x2][y2]-S[x2][y1-1]-S[x1-1][y2]+S[x1-1][y1-1]
递推式:S[i][j]=S[i-1,j]+S[i,j-1]-S[i-1,j-1]+a[i,j]
差分
思想:差分的思想是前缀和思想的逆运算,通过构造一个新的数组,使原来的数
组的每一个元素是新数组的前缀和。
作用:给定一个长度为n的序列a,要求多次做区间加操作,即对a[L]~a[R]
的每个数都加上v。问最后序列a是什么样的。
考虑前缀和的逆变换,a[p]=S[p]-S[p-1],S是a的前缀和
可以通过差分来解决问题或者降低复杂度
递推式:一维——每次a的一个区间[L,R]+=v,等价于b[L]+=v,b[R+1]-=v
二维——b[x][y]=a[x][y]+a[x-1][y-1]-a[x-1][y]-a[x][y-1]
修改矩形[x1,y1,x2,y2]等价于
b[x1][y1]+=v, b[x2+1][y2+1]+=v, b[x1][y2+1]-=v, b[x2+1][y1]-=v。
洛谷题库P2879[Tallest Cow S]
#include<iostream> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> using namespace std; typedef struct ne{ int l,r; friend bool operator<(const ne a, const ne b) { if(a.l == b.l) { return a.r < b.r; } else { return a.l < b.l; } } }node; int change[1000006]; int n, h, sit, r; node list[1000006], temp[1000006]; int main() { cin>>n>>sit>>h>>r; for(int i = 1;i <= r;i++) { cin>>temp[i].l>>temp[i].r; if(temp[i].r < temp[i].l) { swap(temp[i].r, temp[i].l); } } int cnt = 1; sort(temp + 1,temp + 1 + r); for(int i = 1;i <= r;i++) if(temp[i].l != temp[i-1].l || temp[i].r != temp[i-1].r) { list[cnt++] = temp[i]; } { } for(int i = 1;i <= cnt;i++) { change[list[i].l + 1]++; change[list[i].r]--; } for(int i = 1;i <= n;i++) { change[i] = change[i] + change[i - 1]; cout<<(h - change[i])<<endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】