题解:贪婪大陆
树状数组
我们开两个权值树状数组 \(tl,tr\),分别存储布雷的左、右边界。
那么对于给定区间 \([l,r]\),答案即 \(tl.query(r)-tr.query(l-1)\)。
如图:

蓝色即布雷区间,黑色即查询区间。
\(\color{black}\colorbox{black}{1}\) 黑色右区间之前的 \(\color{skyblue}\colorbox{skyblue}{1}\) 蓝色左边界所在区间才有可能与 \(\color{black}\colorbox{black}{1}\) 黑色区间重合。
那么我们再减去 \(\color{black}\colorbox{black}{1}\) 黑色区间左边界左边的 \(\color{skyblue}\colorbox{skyblue}{1}\) 蓝色左边界数量(未重合)即可。
AC 代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=1e5;
struct tree{
int t[N+1];
int lowbit(int x){
return x&-x;
}
void add(int x,int k){
while(x<=N){
t[x]+=k;
x+=lowbit(x);
}
}
int query(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}return ans;
}
}tl,tr;
int n,m;
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
scanf("%d %d",&n,&m);
while(m--){
int q,l,r;
scanf("%d %d %d",&q,&l,&r);
switch(q){
case 1:
tl.add(l,1);tr.add(r,1);
break;
case 2:
printf("%d\n",tl.query(r)-tr.query(l-1));
break;
}
}
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号