题目链接:
http://acm.hit.edu.cn/hoj/problem/view?id=1867
题目大意:
有C家连锁店,编号1~C,有N条指令,每家店初始的商品数目都是M。接下来N行是命令。
命令0:0 x w,连锁店x的商品数量变化为w,w > 0商品数量增加,w < 0商品数量减少。
命令1:1 x y,询问编号区间为[x,y]的连锁店商品为素数的商店有多少家。
思路:
因为区间比较大,所以用树状数组来做。用一个数组Shop[]来存放每家店的商品数目,Tree[]
表示树状数组。如果初始商品数量m是素数的话,则每家商店商品都为素数,遍历更新每家店。
对于命令0,如果该店铺x的商品数Shop[x]为素数,先更新Updata(x,-1),将Shop[x]先视为
不是素数。再将Shop[x] += w,并判断Shop[x]是否为素数,如果为素数,则Updata(x,1)。
这样更新后结果就正确了。对于命令1,则输出:Query(y)-Query(x-1)即可。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #define LL long long using namespace std; int Tree[1000010],Shop[1000010],N = 1000000; int Lowbit(int x) { return x &(-x); } void Update(int i,int x) { while(i <= N) { Tree[i] += x; i += Lowbit(i); } } LL Query(int n) { LL sum = 0; while(n > 0) { sum += Tree[n]; n -= Lowbit(n); } return sum; } bool IsPrime(int x) { if(x <= 1) return 0; for(int i = 2; i <= sqrt(x*1.0); ++i) if(x % i == 0) return false; return true; } int main() { int n,m,c,kase = 0; while(~scanf("%d%d%d",&c,&n,&m) && (c||n||m)) { printf("CASE #%d:\n",++kase); memset(Tree,0,sizeof(Tree)); bool temp = IsPrime(m); for(int i = 1; i <= c; ++i) { // if(IsPrime(m)) if(temp) Update(i,1); Shop[i] = m; } int op; for(int i = 0; i < n; ++i) { scanf("%d",&op); if(op == 0) { int x,w; scanf("%d%d",&x,&w); if(IsPrime(Shop[x])) Update(x,-1); Shop[x] += w; if(IsPrime(Shop[x])) Update(x,1); } else { int x,y; scanf("%d%d",&x,&y); printf("%lld\n",Query(y)-Query(x-1)); } } printf("\n"); } return 0; }
时间: 2024-10-27 11:52:10