Description
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)
Input
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作
Output
对于每个k=2输出一个答案
Sample Input
5 4
1 1 3
2 2 5
1 2 4
2 3 5
Sample Output
1
2
Hint
范围:20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
思路:
这题就是树状数组的模板
我们考虑如何更改区间值
因为树状数组的本质是前缀和,我们想到用差分
求和同理
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<cstring>
using namespace std;
long long n, m;
long long c[100100], a[100100];
long long VL_lowbit(long long x){return (x) & (-x);}
void VL_change(long long x, long long y)
{
for(; x<=n; x+=VL_lowbit(x))
c[x]+=y;
}
long long VL_find(long long x)
{
long long ans=0;
for(; x>0; x-=VL_lowbit(x))
ans+=c[x];
return ans;
}
void VL_change1(long long x, long long y)
{
for(; x<=n; x+=VL_lowbit(x))
a[x]+=y;
}
long long VL_find1(long long x)
{
long long ans=0;
for(; x>0; x-=VL_lowbit(x))
ans+=a[x];
return ans;
}
int main(){
scanf("%lld%lld", &n, &m);
for(long long i=1; i<=m; i++)
{
long long k, x, y;
scanf("%lld%lld%lld", &k, &x, &y);
if(k==1)
{
VL_change(x, 1);
VL_change1(y+1, 1);
}
else
{
printf("%lld\n", VL_find(y)-VL_find1(x));
}
}
return 0;
}