P2184 贪婪大陆(树状数组)

题意:

第一种操作是每次在一个区间布置添加一种地雷,第二种操作求指定区间地雷种类。

思路:

利用前缀和的思想,[L,R]之间的地雷种数等于1~R之间的地雷种数减去 1~R之间那些没有在[L,R]之间的种数。
1到R之间的地雷种数就是1~R之间的左端点个数。
没有布置到[L,R]之间的,就是在1~L-1里就已经布置结束的个数,也就是1到L-1之间的右端点个数。
所以就用树状数组维护前缀的左端点与右端点个数即可。布置一次地雷在左端点处左端点数加1,右端点处右端点数加1。

代码:

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
int c[5][maxn];
int n,m;
int lowbit(int x)
{
    return x&(-x);
}
int sum(int x,int op)
{
    int res=0;
    while(x>0)
    {
        res+=c[op][x];
        x-=lowbit(x);
    }
    return res;
}
void add(int x,int d,int op)
{
    while(x<=n)
    {
        c[op][x]+=d;
        x+=lowbit(x);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int q,l,r;
        scanf("%d%d%d",&q,&l,&r);
        if(q==1)
        {
            add(l,1,1);//1代表左端点个数,2代表右端点个数
            add(r,1,2);
        }
        else if(q==2)
            printf("%d\n",sum(r,1)-sum(l-1,2));
    }
    return 0;
    /*树状数组前缀和的思想。[L,R]之间的地雷种数等于1~R之间的地雷种数(1~R之间左端点的个数)减去1~R之间那些没有在[L,R]之间出现的种数*/
    /*没有布置到[L,R]之间出现的种数就是在1~L-1之间就布置结束的种数,也就是1~L-1之间右端点的个数*/
}

你可能感兴趣的:(树状数组)