310 字
1 分钟
基础-前缀和与差分数组
前缀和
核心作用与缺陷
- 对于需要频繁求子数组范围求和的问题可以优化到o(1)
- 但是数据不可以变更,否则前缀和数组变更的复杂度为o(n)
因此,如果不需要用到原数组,可以不保存原数组
根据核心作用
构建前缀和数组pre后
- 求某一区间和[L,R]:pre[R]-pre[L-1]
- 求某个数R:pre[R+1]-pre[L]
题
未排序数组中累加和为给定值的最长子数组长度_牛客题霸_牛客网
int n,m;
void solve(){ cin>>n>>m; vector<ll>pre(n+1,0); unordered_map<ll,int> hp; hp[0]=0; // 解决前缀和刚好等于m的这个特殊情况,可以可以直接写特判 int ans=0; for(int i=1;i<=n;i++){ cin>>pre[i]; pre[i]+=pre[i-1]; if(hp.find(pre[i])==hp.end()){ hp[pre[i]]=i; } if(pre[i]==m){ ans=max(ans,i); } else if(hp.find(pre[i]-m)!=hp.end()){ ans=max(ans,i-hp[pre[i]-m]); } } cout<<ans;}560. 和为 K 的子数组
int subarraySum(vector<int>& nums, int k) { int n=nums.size(); vector<int> pre(n+1,0); for(int i=1;i<=n;i++){ pre[i]=nums[i-1]; pre[i]+=pre[i-1]; } unordered_map<ll,ll> hp; ll ans=0; hp[0]=1; for(int i=1;i<=n;i++){ if(pre[i]==k){ ans+=hp[0]; } if(hp.find(pre[i]-k)!=hp.end()){ ans+=hp[pre[i]-k]; } hp[pre[i]]++; } return ans;}未排序数组中累加和为给定值的最长子数组系列问题补1
int n;
void solve(){ cin>>n; vector<int> pre(n+1,0); unordered_map<int,int> hp; int ans=0; for(int i=1;i<=n;i++){ int x;cin>>x; if(x>0){ pre[i]=1; pre[i]+=pre[i-1]; } else if(x<0){ pre[i]=-1; pre[i]+=pre[i-1]; } else{ pre[i]=x; pre[i]+=pre[i-1]; } if(pre[i]==0){ ans=max(ans,i); } else if(hp.find(pre[i])!=hp.end()){ ans=max(ans,i-hp[pre[i]]); } if(hp.find(pre[i])==hp.end()){ hp[pre[i]]=i; } } cout<<ans;}1124. 表现良好的最长时间段
按理来讲在找这种情况既要考虑找比小又要i最小,理论上要维护两个值,但是由于划归后整个前缀和数组的变化趋势是连续的且首项一定是0,因此当你要找比还要小的值时,如果存在这个答案,那么一定还有一个在这个答案前面,因为这个答案本身也是通过和-1贡献计算出来的
int longestWPI(vector<int>& hours) { int n=hours.size(); vector<int> pre(n+1,0); unordered_map<int,int> hp; int ans=0; for(int i=1;i<=n;i++){ if(hours[i-1]>8){ pre[i]=1; } else{ pre[i]=-1; } pre[i]+=pre[i-1]; if(pre[i]>0){ ans=max(ans,i); } else{ if(hp.find(pre[i]-1)!=hp.end()){ ans=max(ans,i-hp[pre[i]-1]); } } if(hp.find(pre[i])==hp.end()) hp[pre[i]]=i; } return ans;} 分享
如果这篇文章对你有帮助,欢迎分享给更多人!
基础-前缀和与差分数组
https://blog.hydrodyio.xyz/posts/基础-前缀和与差分数组/ 部分信息可能已经过时
相关文章 智能推荐








