HOJ1867 经理的烦恼【树状数组】

题目链接:

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

HOJ1867 经理的烦恼【树状数组】的相关文章

hoj 1867 经理的烦恼 树状数组

链接:http://acm.hit.edu.cn/hoj/problem/view?id=1867 谁说是入门题啊,真想拍他一巴掌 经理的烦恼 My Tags   (Edit)   Source : HCPC 2005 Spring   Time limit : 2 sec   Memory limit : 32 M Submitted : 2578, Accepted : 606 Jerry是一家公司销售部门的经理.这家公司有很多连锁店,编号为1,2,3,... Jerry每天必须关注每家连锁

BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组

题目大意:给出平面中的一些点,询问平面中的一些矩形中有多少点. 思路:正常应该是二维树状数组,然后数据范围太大.所以就只能按照一个坐标排序,另一个坐标跑树状数组.注意离线操作,一个问题拆成4个. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 500010 #define RANGE 10000010 using n

BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

题目大意:给定平面上的一些点,多次询问某个矩形中有多少个点 将每个询问拆成4个 然后把所有询问和点都按照横坐标排序 对于每个询问,将所有x值小于等于这个询问的x的点的y值加入树状数组 然后在树状数组上查询小于等于这个询问的y值的点的数量 别被1000W吓到了 如果不爆内存的话1E也是能搞的 套个log就没多少了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 [树状数组 离线 离散化]

传送门 刚才我还在郁闷网上怎么没人用$CDQ$分治做 突然发现根本没有时间序.... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=3e6+5; inline int read(){ char c=getchar();int x=0,f=1; whi

区间素数个数 树状数组 HIT 1867 经理的烦恼

http://acm.hit.edu.cn/hoj/problem/view?id=1867 经理的烦恼   Source : HCPC 2005 Spring   Time limit : 2 sec   Memory limit : 32 M Submitted : 2994, Accepted : 686 Jerry是一家公司销售部门的经理.这家公司有很多连锁店,编号为1,2,3,... Jerry每天必须关注每家连锁店的商品数量及其变化,一项很乏味的工作.在连锁店比较少的时候,Jerry

HOJ 1867 经理的烦恼 【 树状数组 】

题意:给出一个区间,求这个区间里面素数的个数 这道题wa了好多次---是因为add操作没有写对 每次更新的时候,应该先判断没有加上y是不是质数,加上了y是不是质数 如果从质数变成不是质数,那么add(x,-1) 如果从不是质数变成是质数,那么add(x,1) 另外还pe了,,printf("\n")就不对,puts("")就对了 ---不懂-------- 1 #include<iostream> 2 #include<cstdio> 3 #

树状数组实践-HIT经理的烦恼

点击打开HIT 1867 思路: 树状数组 分析: 1 题目要求的是给定一个区间求这个区间质数的个数 2 题目给定n条命令和每个店的初始的值,那么我们初始化的时候就要通过判断给定的初始值是否为质数来初始化 3 因为要求的是质数的个数,那么我们可以这么想,假设现在改变了店铺x的值,那么我们通过判断前后是否是质数的关系来更新树状数组 4 求区间的质数的个数的时候直接求即可 <span style="font-size:14px;">#include <cmath>

【BZOJ1935/4822】[Shoi2007]Tree 园丁的烦恼/[Cqoi2017]老C的任务 树状数组

题意:两道题差不多,都是给你一堆平面上的点,每个点有权值,然后m次询问求某一矩形区域内的点权和 题解:先离散化,然后将询问拆成左右两条线段,然后将点和这些线段一起按x坐标排序,在y轴上维护树状数组.然后询问的答案就是两条线段上点权和之差 BZOJ1935: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int

$[SHOI2007]$ 园丁的烦恼 二维数点/树状数组

\(Sol\) 设一个矩阵的左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\),\(s_{x,y}\)是到\((1,1)\)二维前缀和,那么这个矩阵的答案显然是\(s_{x_2,y_2}-s_{x_1-1,y_2}-s_{x_2,y_1-1}+s_{x_1-1,x_2-1}\).考虑把每个询问拆成这么四个二维前缀和的询问.将所有询问的\(s_{x,y}\)按照\(x\)排序,依次计算,这样我们就可以忽略\(x\)的限制而只考虑\(y\)的限制了.每次扫到一个询问,先把\(x\