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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值