scu 2057 樹狀陣列 單點更新區間求和問題
阿新 • • 發佈:2019-01-24
連結: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;
}