校门外有很多树,学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两种操作:
- K=1,读入l,r 表示在l 到 r 之间种上一种树,每次操作种的树的种类都不同;
- K=2,读入 l,r 表示询问 l 到 r 之间有多少种树。
注意:每个位置都可以重复种树。
输入格式
第一行 表示道路总长为 n,共有 m个操作;
接下来 m 行为 m 个操作。
输出格式
对于每个 K=2 输出一个答案。
样例
样例输入
5 4
1 1 3
2 2 5
1 2 4
2 3 5
样例输出
1
2
题解:这道题开两个数组 ,一个sum1维护左端点的数目,另一个数组sum2维护右端点的数目。这样区间[l,r]的树的种类的数目就是1到r中左端点的数目减去1到(l-1)中右端点的数目,表示成sum1[r]-sum2[l-1]。
代码如下:
#include<stdio.h>
#include<string.h>
int n,m;
int sum1[50005];
int sum2[50005];
int lowbit(int x){
return x&(-x);
}
void updata1(int i,int k){
int x = i; //因为x不变,所以得先保存i值
while(i <= 50005){
sum1[i] += k;
i += lowbit(i);
}
}
void updata2(int i,int k){
int x = i; //因为x不变,所以得先保存i值
while(i <= 50005){
sum2[i] += k;
i += lowbit(i);
}
}
int getsum1(int i){ //求前缀和
int res = 0;
while(i > 0){
res += sum1[i];
i -= lowbit(i);
}
return res;
}
int getsum2(int i){ //求前缀和
int res = 0;
while(i > 0){
res += sum2[i];
i -= lowbit(i);
}
return res;
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int e,x,y;
scanf("%d%d%d",&e,&x,&y);
if(e==1)
{
updata1(x,1); //A[x] - A[x-1]增加k
updata2(y,1); //A[y+1] - A[y]减k;
}
else
{
int sum = getsum1(y) - getsum2(x-1);
printf("%d\n",sum);
}
}
return 0;
}