校门外的树 (树状数组)题解
题目
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K
K
K=1,读入
l
l
l,
r
r
r表示在
l
l
l~
r
r
r之间种上的一种树
K
K
K=2,读入
l
l
l,
r
r
r表示询问l~r之间能见到多少种树
(
l
l
l,
r
r
r>0)
输入
第一行
n
n
n,
m
m
m表示道路总长为
n
n
n,共有
m
m
m个操作
接下来
m
m
m行为
m
m
m个操作
输出
对于每个 k k k=2输出一个答案
样例
input
5 4
1 1 3
2 2 5
1 2 4
2 3 5
output
1
2
解题思路
树状数组
找下一位的操作:
l
o
w
b
i
t
lowbit
lowbit(
x
x
x & (-
x
x
x))
举个栗子:
(6)10=(110)2
(-6)10=(010)2
原数+lowbit得8
原数-lowbit得4
这种神神奇奇的东西,不能言传只能意会
累加时
左边统计左括号(也就是左边界)
右边统计右括号(也就是右边界)
询问时
1~右边界里有几个左括号
减去
1~左边界-1里有几个右括号
代码
#include<iostream>
#include<cstdio>
using namespace std;
int p,l,r,n,m,a[50100],b[50100];
void add(int x)
{
for (;x<=n;x+=x & (-x))
a[x]++;
}
void add2(int x)
{
for (;x<=n;x+=x & (-x))
b[x]++;
}
int tj2(int x)
{
int sum=0;
for (;x>0;x-=x & (-x))
sum+=a[x];
return sum;
}
int tj(int x)
{
int sum=0;
for (;x>0;x-=x & (-x))
sum+=b[x];
return sum;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&l,&r);
if (p==1)
add(l),add2(r);
else printf("%d\n",tj2(r)-tj(l-1));
}
return 0;
}