传送门:校门外的树
原本的是求一段区间内的树的数量,现在求的是一段区间内树的总数。
思路:利用括号序列的思想,设一段种树的区间由一个左括号和一个有括号括起来。左括号的位置是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;
}