前缀和与差分
作者:互联网
前缀和
*一维
定义:一维前缀和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; }
标签:前缀,temp,int,差分,二维,一维,include 来源: https://www.cnblogs.com/dd90901/p/16526279.html