HOJ 1867 经理的烦恼 树状数组
/*
题目:
给出n个商店,每个商店有初始化的商品数量,现在有两种指令:
0 x y 连锁店x的商品数量变化值为y,y > 0商品数量增加, y < 0减少
1 i j 输出编号在[i,j]区间内的连锁店中商品数量为素数的有多少家
当指令为1时,求给出 i到j的商品数量为素数的商店的数目
分析:
用树状数组做,只不过在update()处改动一下,并且注意到有可能改动完后和改动前
均为素数的情况,所以用visit[]数组记录此前是否为素数,另外需要注意的是当初始
化时即为奇数的话,当时就要初始化数组c[]以及visit[]数组
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int X = 1000010;
int a[X],c[X],n,m,k;
bool visit[X];
bool check(int x) //判断是否是素数
{
if(x<=1) //小于等于一直接返回false
return false;
for(int i=2;i*i<=x;i++)
if(x%i==0)
return false;
return true;
}
int lowbit(int x)
{
return x & -x;
}
int sum(int x) //求和
{
int ans = 0;
while(x>0)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
void update(int x)
{
if(check(a[x])) //如果这个商店的商品数为素数
{
if(!visit[x]) //如果之前不是素数的话,现在为素数
{
visit[x] = true;
while(x<=n)
{
c[x]++;
x += lowbit(x);
}
}
}
else //如果这个商店的商品数为偶数
{
if(visit[x]) //如果之前是素数,但现在不是素数
{
visit[x] = false;
while(x<=n)
{
c[x]--;
x += lowbit(x);
}
}
}
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int x,y,z,cnt = 0;
while(scanf("%d%d%d",&n,&m,&k),n||m||k)
{
printf("CASE #%d:\n",++cnt);
for(int i=1;i<=n;i++) //初始化
a[i] = k;
if(check(k)) //如果刚开始即为素数
{
for(int i=1;i<=n;i++)
{
c[i] = lowbit(i);
visit[i] = true; //visit数组为true时表示之前的数为素数
}
}
else
{
memset(c,0,sizeof(c));
memset(visit,false,sizeof(visit));
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
if(z)
printf("%d\n",sum(y)-sum(x-1));
//计算的是[i,j]的区间内的连锁店中商品数量为素数的有多少家
else
{
a[x] += y; //x商店的变化
update(x); //更新x商店的变化给其他商店带来的变化
}
}
cout<<endl;
}
return 0;
}