模板 树状数组

步行街
Time Limit: 3000 MSMemory Limit: 32768 K
Total Submit: 79(36 users)Total Accepted: 38(33 users)Rating: Special Judge: No
Description

小A管理着一条大的步行街,步行街上有N家店铺,每家店铺都有很多种商品,小A的工作就是记录每家店铺的商品数。

并且大boss会时常询问小A,从第i家店铺到第j家店铺中有多少家店铺有奇数种商品。但是,每家商品有的时候会进入或下架一些商品,小A来寻求你的帮助了。

Input

多组输入数据:

每组数据第一行有两个整数:N :代表步行街上的店铺数(0<N<50000);m:大boss的m个询问(0<m<5000);

第二行有n个数:代表从第一家到最后一家,每一家店铺的商品数num(0<num<50000)。

接下来的m行:

C x y代表第x家店铺改变的值y(正数代表上架,负数代表下架,保证数据合理)。

Q i j代表询问第i家店铺到第j家店铺中有多少家店铺有奇数种商品。

Output

对于每次大boss的询问:输出结果,每个结果占一行。

Sample Input
5 3
1 2 3 4 5
Q 1 5
C 3 1
Q 1 5



—————————————————————————————————————————————————————————————————————————————

解题思路:

   

我们保留原来的商店的信息为numi,记录第i家商店的商品数。

我们将ai】定义为第i家店铺的商品是不是奇数,是的话等于1,不是的话等于0,

那么sumi)求出的就是第1家商店到第i家商店一共有几家商店是奇数。这个可以画个x坐标轴理解下。

每次修改值的时候,我们要做的是:看改变前的和改变后的奇偶性发生改变了么,奇偶性没发生变化话的话,我们可以

只修改下numi】的值;当奇偶性不同的时候:

原来为奇数,之后为偶数,那么我们就让addi-1),这样ai】就从1变成0了。

#include <iostream>
#include <string.h>
#include <stdio.h>


#define maxn 50000 +5


using namespace std;
int num[maxn];
int c[maxn];
int n;


int lowbit(int i)
{
    return i &- i;
}


void update(int i, int j)
{
    while( i <= n)
    {
        c[i] += j;
        i += lowbit(i);
    }
}


int sum(int i)
{
    int ans = 0;
    while( i > 0)
    {
        ans += c[i];
        i -=lowbit(i);
    }
    return ans;
}


int main(void)
{   int m;
    int x,y;
    char a;
    while(scanf("%d%d",&n, &m) != EOF)
    {   memset(c,0,maxn);
        for(int i = 1; i<=n; i++)
        {
            scanf("%d",&num[i]);
            if(num[i] % 2 == 1)
              update(i, 1);
        }
        for( int i = 1; i<=m; i++)
        {
            scanf("%c%d%d",&a, &x, &y);


            if(a == 'C')
            {
                 if(num[x] % 2 == 0 )
                 {
                     if((num[x] + y)%2 == 1)
                       update(x,1);
                 }
                if(num[x] % 2 == 1)
                  {
                      if((num[x] + y) %2 == 0)
                       update(x,-1);
                  }
                num[x] += y;
            }
            if(a == 'Q')
            {


                cout<<sum(y)-sum(x-1)<<endl;
            }


        }


    }
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值