1. 程式人生 > >scu 2057 樹狀陣列 單點更新區間求和問題

scu 2057 樹狀陣列 單點更新區間求和問題

連結: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; }