1458 区间问题(区间贡献问题超全详解)


题目链接

题源

大概题意:
给定你n个数字 a i a_i ai,请你求出有多少个区间[l,r],满足该区间的数字之和等于其区间长度。
n<=1e5,-1e9<=<=1e9

思路:

前缀和+思维

对于两个数 a i , a j a_i,a_j ai,aj来说,如果满足以 a i a_i ai为左界,以 a j a_j aj为右界包含的区间和等于区间长度
则满足 s u m [ j ] − s u m [ i − 1 ] = j − i + 1 sum[j]-sum[i-1]=j-i+1 sum[j]sum[i1]=ji+1

将公式转换一下就是 s u m [ j ] − j = s u m [ i − 1 ] − ( i − 1 ) , ( i ≤ j ) sum[j]-j=sum[i-1]-(i-1),(i\le j) sum[j]j=sum[i1](i1),(ij)
更一般的来说,将公式变为 s u m [ j ] − j = s u m [ i ] − i , ( i < j ) sum[j]-j=sum[i]-i,(isum[j]j=sum[i]i,(i<j)

接下来的问题就变为找sum[i]-i出现的个数,对于 a j a_j aj来说,前面有出现多少个sum[j]-j,结果就加上多少,表示 a j a_j aj能够与前面的数组成满足条件的区间数。

对于每个 a j a_j aj来说,前面与sum[j]-j相同的个数都要加上去,所以就是要累加 s u m [ j ] − j sum[j]-j sum[j]j出现的次数,以便后边使用。

注意:
一定要初始化一个值,因为这我找了好长时间的错。
mp[0]代表初始化第0个元素


为什么呢?


因为如果表示 a 1 a_1 a1 a j a_j aj整个区间时,初始式子为
s u m [ j ] − s u m [ 0 ] = j − 0 sum[j]-sum[0]=j-0 sum[j]sum[0]=j0,把0这个元素记上去,才能记录表示整个区间的答案。

好多类似思路的题目(几乎是异曲同工):

链接1 的第二和第三题
链接2 的C题

可以点一下看看,对自己的帮助和提高很大

代码:

#include
using namespace std;
typedef long long ll;
const int N = 1e6+5;
ll a[N];
int main()
{
     
	int n;
	cin>>n;
	map<ll,ll>mp;
	ll ans=0,sum=0;
	mp[0]=1;
	for(int i=1;i<=n;i++)
	{
     
		cin>>a[i];
		sum += a[i];
		ans += mp[sum-i];
		mp[sum-i]++;
	}
	cout<<ans<<'\n';
	return 0;
 } 

你可能感兴趣的:(题解思路,算法,数据结构,新星计划,动态规划)