树状数组——校门外的树进阶版

传送门:校门外的树

原本的是求一段区间内的树的数量,现在求的是一段区间内树的总数。

思路:利用括号序列的思想,设一段种树的区间由一个左括号和一个有括号括起来。左括号的位置是l, 右括号的位置是 r.

如果要求求某一段区间[l,r]内的树的种类,那就是拿r(及其自身)前面的所有左括号的数量减去l-1(及其自身)前面所有右括号的数量。容易想到最终得到的数字就是区间内的树的种类。 

这一点可以用两个树状数组实现,两个数组的前缀和sum[i]分别用来表示位置[i]前面的左括号的数量和位置[i]前面的右括号的数量。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e6+10;
int n,m;
int a[N];
int c1[N];
int c2[N];
int lowbit(int x)
{
    return x&-x;
}
void add(int c[],int x,int y)
{
    for(;x<=n;x+=lowbit(x))
        c[x]+=y;
}
int ask(int c[],int x)
{
    int ans=0;
    for(;x;x-=lowbit(x))  ans+=c[x];
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int x,l,r;
        scanf("%d%d%d",&x,&l,&r);
        if(x==1)
        {
            add(c1,l,1);
            add(c2,r,1);
        }else
        {
            printf("%d\n",ask(c1,r)-ask(c2,l-1));
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值