经典问题:查询有多少段区间和等于k值

题目连接
题意:在大小为1e5以内的数组求存在多少个区间和的值等于k的次方
这种题很经常见,总是想着用两个for循环解决,但是一定会超时。
题解:算出前缀和,使用map去查找mp[sum[i+1]-tmp]的个数,加起来就是答案,这样复杂度在O(n)加上mp的查找时间,基本上不会超时

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define de(x) cout << #x << "=" << x << endl
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define pb push_back
#define fi first
#define se second
const int N = 1e5+5;
const ll eps = 1e15;
ll a[N];
ll sum[N];
map<ll,int>mp;
int main()
{
	ll n,k,i,j;
	ll tmp=1;
	ll ans=0;
	scanf("%lld%lld",&n,&k);
	sum[0]=0;
	for(i=1;i<=n;i++) {scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}
	for(i=0;i<n;i++)
	{
		mp[sum[i]]++;
		tmp=1;
		while(tmp<eps&&k!=-1&&k!=1)
		{
			if(mp[sum[i+1]-tmp]!=0) ans+=mp[sum[i+1]-tmp];
			tmp=tmp*k;
		}
		if(k==-1)
		{
			if(mp[sum[i+1]-1]!=0) ans+=mp[sum[i+1]-1];
			if(mp[sum[i+1]+1]!=0) ans+=mp[sum[i+1]+1];
		}
		else if(k==1)
		{
			if(mp[sum[i+1]-1]!=0) ans+=mp[sum[i+1]-1];
		}
	}
	cout<<ans<<endl;
} 
posted @ 2017-10-22 15:38  Linese  阅读(839)  评论(0编辑  收藏  举报