校门外的树(树状数组)

题目传送门

题目给定一段道路,每次对一个区间上种树,每次种的树保证不是同一种,同一位置可以中多棵树,每次询问一个区间,问这个区间里有多少种树。

思路
我们每次把种树的位置用树状数组去维护,对于一个询问,我们只要询问在右端点(闭区间)内有多少个种树的左端点,左端点(开区间)内有多少种树的右端点,相减即可(即有多少个区间完全不在询问的区间内)。
需要两个数组去分别维护种树的左右端点。

代码

#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));
    }
}
发布了93 篇原创文章 · 获赞 9 · 访问量 4204

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/104432707
今日推荐