算法竞赛进阶指南基础算法:前缀和与差分
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法竞赛进阶指南基础算法:前缀和与差分相关的知识,希望对你有一定的参考价值。
激光炸弹
题
求一颗炸弹炸掉的最大价值,就是求以R为边长的正方形的覆盖范围的价值最大值。
用二维前缀和把图跑一遍(构造),然后再跑一遍(遍历求R*R);
知道公式直接套用即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
#define mem(a,x) memset(a,x,sizeof(a));
const int N=5010;
int a[N][N];
int t,r,n,m;
int main()
{
scanf("%d%d",&t,&r);
r=min(r,5002);//r范围再大也打不过正方形的最大范围
n=m=r;
while(t--)
{
int x,y,w;scanf("%d%d%d",&x,&y,&w);
x++,y++;//前缀和要从1开始 所以范围要+1
a[x][y]+=w;
n=max(n,x);
m=max(m,y);//已知的最大边界
}
//求二维前缀和
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]+=(a[i-1][j]+a[i][j-1]-a[i-1][j-1]);
}
}
//求边长为R的正方形的前缀和
int ans=0;
for(int i=r;i<=n;i++)
{
for(int j=r;j<=m;j++)
{
ans=max(ans,a[i][j]-a[i-r][j]-a[i][j-r]+a[i-r][j-r]);
}
}
printf("%d",ans);
return 0;
}
增减序列
差分:关于为什么是ans2=z-f+1种,我是这样理解的:
a 1 1 1 1 6
b 1 0 0 0 5
a是原数组,b是差分数组。现在只有最后一个6是要改的,不管怎么样都要操作5次:
那我们就可以让a数组全变成1、2、3、4、5、6,
分别对应6-5,6-4和1+1,6-3和1+2等等....
那我们就会有1,2,3,4,5,6这6种,即5+1.
同时,对于计正负数从2开始是因为b从2开始才是差,b[1]只是a[1],不是差。
代码:注意LL;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
#define mem(a,x) memset(a,x,sizeof(a));
const int N=1e5+10;
int n;
ll a[N],b[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++) b[i]=a[i]-a[i-1];
ll z=0,f=0;
for(int i=2;i<=n;i++)
{
if(b[i]>0) z+=b[i];
else if(b[i]<0) f+=b[i];
}
ll ans=0;
f=abs(f);
if(z<f) swap(z,f);//让z大
ans+=f;
ans+=(z-f);
ll ans2=z-f+1;
printf("%lld\\n%lld",ans,ans2);
return 0;
}
最高的牛
题
差分和前缀和的综合应用~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
#define mem(a,x) memset(a,x,sizeof(a));
const int N=1e4+10;
int cow[N];
int n,p,h,m;//p最高为h
map<pii,int>mp;
int main()
{
scanf("%d%d%d%d",&n,&p,&h,&m);
for(int i=0;i<m;i++)
{
int a,b;scanf("%d%d",&a,&b);
if(mp.count({a,b})) continue;
if(a>b) swap(a,b);
mp[{a,b}]++;
cow[a+1]--;
cow[b]++;
}
for(int i=2;i<=n;i++) cow[i]=cow[i]+cow[i-1];
for(int i=1;i<=n;i++)
{
printf("%d\\n",cow[i]+h);
}
return 0;
}
以上是关于算法竞赛进阶指南基础算法:前缀和与差分的主要内容,如果未能解决你的问题,请参考以下文章