[树状数组]校门外的树
校 门 外 的 树 校门外的树 校门外的树
题目描述
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K
=
1
K=1
K=1,读入
l
,
r
l,r
l,r表示在
l
r
l~r
l r之间种上的一种树(
l
,
r
>
0
l,r>0
l,r>0)
K
=
2
K=2
K=2,读入
l
,
r
l,r
l,r表示询问
l
r
l~r
l r之间能见到多少种树(
l
,
r
>
0
l,r>0
l,r>0)
输入
第一行
n
,
m
n,m
n,m表示道路总长为
n
n
n,共有
m
m
m个操作
接下来
m
m
m行为
m
m
m个操作
输出
对于每个 k = 2 k=2 k=2输出一个答案
样例输入
5 4
1 1 3
2 2 5
1 2 4
2 3 5
样例输出
1
2
数据范围
20
20
20%的数据保证,
n
,
m
<
=
100
n,m<=100
n,m<=100
60
60
60%的数据保证,
n
<
=
1000
,
m
<
=
50000
n <=1000,m<=50000
n<=1000,m<=50000
100
100
100%的数据保证,
n
,
m
<
=
50000
n,m<=50000
n,m<=50000
题目解析
首先看题,不难看出是区间修改和区间查询。
可以用线段树和树状数组来实现代码
但因为数据规模较大,所以我们选择了时间复杂度较小的树状数组
在程序中的lowbit函数, − x -x −x 的值,其实就是在x的值的基础上进行按位取反 (~ x x x)之后在增加1所得,也是运用到一个二进制优化。
x & (-x) = x & (~x + 1)
那么如果 x x x 是一个偶数,那么就可以得出
- x x x & ( − x ) (-x) (−x) = 2 2 2x
那么如果 x x x是一个奇数,那么就可以得出
- x x x & ( − x ) (-x) (−x) = 1 1 1
不信?那么可以自己推一下(
code
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,a[50005],b[50005];
int lowbit(int x)
{
return x & (-x);
}
void add1(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
b[i]+=k;
}
void add2(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
a[i]+=k;
}
int sum1(int x)
{
int sum=0;
for(int i=x;i;i-=lowbit(i))sum+=a[i];
return sum;
}
int sum2(int x)
{
int sum=0;
for(int i=x;i;i-=lowbit(i))sum+=b[i];
return sum;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
int k,l,r;
scanf("%d%d%d",&k,&l,&r);
if(l>r)
swap(l,r);
if(k==1)
{
add1(r,1);
add2(l,1);
}
else
{
printf("%d\n",sum1(r)-sum2(l-1));
}
}
return 0;
}