解题思路:开始怎么想都不知道怎么维护不同段中树的种类是否相同的情况,感觉这题有个思维技巧还是挺难想的,就是我们要开两个数组,sum1分别维护左端点的数目,另一个数组sum2维护右端点的数目。这样区间[l,r]的树的种类的数目就是1-r中左端点的数目减去1-(l-1)中右端点的数目,即表示为sum1[r]-sum2[l-1]。
如图假如我们第一次在区间a[2,6]种上一种树,然后再在区间b[5,10]种上一种树,这时我们要统计区间c[8,12]中树的种类数目,我们就统计[1,12]中左端点的数目即 sum1[12]等于2,说明有两种树可能在给定区间内,然后我们再求区间[1,7]中右端点的数目即sum2[7]-sum2[1]=1,表示有一种树完全在给定区间左边,并不是我们要求的,所以减去就好了,所以答案就为sum1[12]-(sum2[7]-sum2[1])=1了。
原解析地址:https://www.cnblogs.com/zjl192628928/p/10630450.html
1 #include<iostream> 2 using namespace std; 3 #define lowbit(i) i&(-i) 4 int sum1[100100],sum2[100100]; 5 int n,m; 6 7 void up1(int x,int val){ 8 while (x<=n){ 9 sum1[x]+=val; 10 x+=lowbit(x); 11 } 12 } 13 14 void up2(int x,int val){ 15 while (x<=n){ 16 sum2[x]+=val; 17 x+=lowbit(x); 18 } 19 } 20 21 int q1(int x){ 22 int ret=0; 23 while (x){ 24 ret+=sum1[x]; 25 x-=lowbit(x); 26 } 27 return ret; 28 } 29 30 int q2(int x){ 31 int ret=0; 32 while (x){ 33 ret+=sum2[x]; 34 x-=lowbit(x); 35 } 36 return ret; 37 } 38 39 int main(){ 40 cin>>n>>m; 41 while (m--){ 42 int k,l,r; 43 cin>>k>>l>>r; 44 if (k==1){ 45 up1(l,1); 46 up2(r,1); 47 } 48 else{ 49 cout<<q1(r)-q2(l-1)<<endl; 50 } 51 } 52 return 0; 53 }