题目传送门
题目给定一段道路,每次对一个区间上种树,每次种的树保证不是同一种,同一位置可以中多棵树,每次询问一个区间,问这个区间里有多少种树。
思路
我们每次把种树的位置用树状数组去维护,对于一个询问,我们只要询问在右端点(闭区间)内有多少个种树的左端点,左端点(开区间)内有多少种树的右端点,相减即可(即有多少个区间完全不在询问的区间内)。
需要两个数组去分别维护种树的左右端点。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
#define ls p<<1
#define rs p<<1|1
//#define int long long
int a[N],b[N];
int n,m;
int lowbit(int x)
{
return x&-x;
}
void add1(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
{
a[i]+=k;
}
}
void add2(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
{
b[i]+=k;
}
}
int sum1(int x)
{
int s=0;
for(int i=x;i;i-=lowbit(i))
{
s+=a[i];
}
return s;
}
int sum2(int x)
{
int s=0;
for(int i=x;i;i-=lowbit(i))
{
s+=b[i];
}
return s;
}
signed main()
{
IOS;
//freopen("","r",stdin);
//freopen("","w",stdout);
scanf("%d%d",&n,&m);
while(m--)
{
int k,l,r;
scanf("%d%d%d",&k,&l,&r);
if(l>r)
swap(l,r);
if(k==1)
{
add1(l,1);
add2(r,1);
}
else
printf("%d\n",sum1(r)-sum2(l-1));
}
}