算法竞赛:前缀和与差分的实战解析

#include<bits/stdc++.h>
using namespace std;
int n,m,a[100099],l,r,s[100099];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>l>>r;
		cout<<s[r]-s[l-1]<<endl;
	}
	return 0;
}

这道题是典型前缀和问题,就是求从l~r的和。

#include<bits/stdc++.h>
using namespace std;
int w[10000099]={};
int a[10000099]={};
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		string s;
		cin>>s;
		int q;
		cin>>q;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='P')a[i+1]=3;
			else if(s[i]=='p')a[i+1]=2;
			else if(s[i]=='G')a[i+1]=1;
			else a[i+1]=0;
		}
		for(int i=1;i<=s.size();i++)w[i]=w[i-1]+a[i];
		while(q--)
		{
			int l,r;
			cin>>l>>r;
			cout<<w[r]-w[l-1]<<endl;
		}
	}
	return 0;
}

要注意数组开大,其他与前缀和一样,只不过把数字改为字符。

 

#include<bits/stdc++.h>
using namespace std;
int x[10000099]={};
int b[10000099]={},s[10000000],a[10000000];
int main()
{
	int w,n,h=0,maxx=0;
	cin>>w>>n;
	for(int i=1;i<=w;i++)
	{
		cin>>x[i]>>b[i];
		a[x[i]]+=b[i];
	}
	for(int i=1;i<=1e5;i++)s[i]=s[i-1]+a[i];
	int mx=0;
	for(int i=1;i<=1e5;i++)mx=max(mx,s[i]-s[i-n]);
	cout<<mx;
	return 0;
}

这里也是前缀和,只是一个位置可能有多颗星星,最后要求最大亮度和。

(这题目背景诗人握持)

#include<bits/stdc++.h>
using namespace std;
long long n,p,a[5000005],b[5000005]= {};
int main() {
	cin>>n>>p;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		b[i]=a[i]-a[i-1];
	}
	for(int i=1; i<=p; i++) {
		int l,r,c;
		cin>>l>>r>>c;
		b[l]+=c;
		b[r+1]-=c;
	}
	long long mn=1e9;
	for(int i=1;i<=n;i++)
	{
		a[i]=a[i-1]+b[i];
		mn=min(mn,a[i]);
	}
	cout<<mn;
	return 0;
}

这是一道典型的差分问题,解题时需特别注意题目要求输出最低分值。

#include<bits/stdc++.h>
using namespace std;
int l,r,d[1000005],s[1101001];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>l>>r;
		d[l]++;
		d[r+1]--;
	}
	s[0]=d[0];
	for(int i=1;i<=1e6;i++)
	{
		s[i]=s[i-1]+d[i];
	}
	int mx=0;
	for(int i=0;i<=1e6;i++)
	{
		mx=max(mx,s[i]);
	}
	cout<<mx;
	return 0;
}

本题考察差分技巧,核心在于求解最多被浇水的次数。

#include<bits/stdc++.h>
using namespace std;
int n,k,a[1000005],q[1000005];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i]; 
		q[i]=q[i-1]+a[i];
	}
	int maxx=0;
	for(int i=1;i<=n-k;i++)
	{
		maxx=max(maxx,q[i+k]-q[i-1]);
	}
	cout<<maxx;
	return 0;
}

这是一个关于前缀和的问题,目标是计算最多能喝多少水。

??????????????????????????????????????????

(仅供娱乐) 

#include<bits/stdc++.h>
using namespace std;
long long n,k,a[1000005],q[1000005];
int main()
{
	cin>>n>>k;
	for(int i=2;i<=n;i++)cin>>a[i]; 
	int maxx=0;
	for(int i=1;i<=n;i++)
	{
		q[i]=q[i-1]+a[i];
	}
	long long mx=0;
	for(int i=k;i<=n;i++)
	{
		mx=max(mx,q[i]-q[i-k]);
	}
	cout<<q[n]-mx;
	return 0;
}

也是前缀和,不多说了。 

60秒带你欣赏最帅男角色—宇智波佐助(仅供娱乐)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值