链接:http://acm.scu.edu.cn/soj/problem.action?id=2057
题意:
给定n个店铺,给了初始商品i个。
两种操作,1)将第a个店铺的商品加b个。2)询问a~b这些店铺中有几个商品的数量是一个素数。
做法:
单点更新,区间求和问题,利用树状数组实现。不过我还是比较习惯线段树,但是这题线段树太诡异。。只能放弃治疗。刚好复习一下树状数组吧。。
对于修改操作,如果修改后和原来的数是一样的属性(同是素数,或都不是),就不需要更新这点,如果发生变化了才要。
sum(i)表示 从1~i 之间有几个商店的商品数量是素数。
对于查询a~b 来说就是sum(b) - sum(a-1).
#include <cstdio>
#include <cstring>
#include <algorithm>
#define M 1000050
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int bit[M];
int a[M];
int c,n,m;
bool is_prime(int t)
{
if(t <= 1) return false;
for(int i = 2;i * i <= t;i++)
{
if(t % i == 0) return false;
}
return true;
}
void add(int i,int x)
{
while(i <= c)
{
bit[i] += x;
i += i & -i;
}
}
int sum(int i)
{
int ans = 0;
while(i > 0)
{
ans += bit[i];
i -= i & -i;
}
return ans;
}
int main()
{
int kk = 1;
while(scanf("%d %d %d",&c,&n,&m) == 3)
{
if(c == 0 && n == 0 && m == 0) break;
printf("CASE #%d:\n",kk++);
bool ok = is_prime(m);
memset(bit,0,sizeof(bit));
for(int i = 1;i <= c;i++)
{
a[i] = m;
if(ok) add(i,1);
}
//build(1,c,1);
for(int i = 0;i < n;i++)
{
int t1,t2,t3;
scanf("%d %d %d",&t1,&t2,&t3);
if(t1 == 0)
{
bool ok1 = is_prime(a[t2]);
a[t2] += t3;
bool ok2 = is_prime(a[t2]);
if(ok1 == ok2) continue;
if(ok1 == true && ok2 == false) add(t2,-1);
else if(ok1 == false && ok2 == true) add(t2,1);
}
else printf("%d\n",sum(t3) - sum(t2-1));
}
putchar('\n');
}
return 0;
}