POJ 2739 树状数组的应用

我这里显示离散化了2-1000的质数,把集合1-index,每个对应质数2,3,5,7,11…
我们可以知道如果查询的是n,又需要质数连续,假设i-j区间和为n,则ans++。这就是最朴素的思路。
我们顺着这个思路假设用最古老的方法,先遍历一遍已经做好的集合,算出sum,这样太慢了。
我们看到这道题用在了,单点更新,求区间前缀和,想到最快的方法,就是树状数组了。
那么就用树状数组来求前缀和就好了。
其中每个区间用尺取法来维护。
14ms就能跑出答案了。
注意尺取法的时候,r和l的取最大时候的取值。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const long long INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int, int> pir;
int n;
bool use[10005];
int temp[10005];
int index = 1;
int mp[10005];
int lowbit(int i)
{
	return i & (-i);
}//求下一个i需要加减的值
void add(int i, int k)
{
	while (i < index)
	{
		temp[i] += k;
		i += lowbit(i);
	}
}//添加
void prime()
{
	for (int i = 2; i <= 10000; i++)
	{
		for (int j = i + i; j <= 10000; j += i)
		{
			if (use[j])
				use[j] = false;
		}
	}
	up(i, 1, 10001)
	{
		if (use[i])
		{
			//cout << i << endl;
			mp[index] = i;
			index++;
		}
	}
	up(i, 1, index)
	{
		add(i,mp[i]);
	}
}//离散化素数
int qsum(int i)
{
	int sum = 0;
	while (i)
	{
		sum += temp[i];
		i -= lowbit(i);
	}
	return sum;
}//树状数组求和
int main()
{
	fill(use, use+10001, true);
	use[0] = use[1] = false;
	int lf, rt; int ans;
	prime();//初始化
	while (scanf("%d", &n) && n)
	{
		lf = 0;
		rt = 1;
		ans = 0;
		int temp = lower_bound(mp, mp + 10005, n)-mp+1;//查找一下下标为最大下标
		while (lf < rt&&rt<=temp)//尺取法
		{
			if (qsum(rt) - qsum(lf) <n)
				rt++;
			else if(qsum(rt)-qsum(lf)==n)
			{
				ans++;
				lf++;
			}
			else lf++;
		}
		cout << ans << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值