分块

本文介绍了一种基于块的数据结构实现,用于高效处理区间更新和查询操作。包括区间加法、区间乘法、区间覆盖等操作,并能进行单点查询、查询区间内特定条件的元素等多种查询任务。
1.区间加, 查询单点值
struct block
{
    static const int __=50005;
    static const int _b_=300;
    ll a[__];int n,bsz,bel[__];
    ll ad[_b_];

    ll operator[](int x){return a[x]+ad[bel[x]];}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            bel[i]=(i-1)/bsz+1;
    }

    void add(int l,int r,ll val)
    {
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]+=val;
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            ad[i]+=val;
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]+=val;
    }

    void clear(){memset(ad,0,sizeof(ad));}
}b;
2.区间加, 查询区间内小于某个数的个数
struct block
{
    static const int __=50005;
    static const int _b_=300;
    ll a[__];int n,bsz,bel[__];
    ll ad[_b_];
    vector<ll>ord[_b_];

    ll operator[](int x){return a[x]+ad[bel[x]];}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            ord[bel[i]=(i-1)/bsz+1].pb(a[i]);
        for(int i=1;i<=bel[n];i++)
            sort(ord[i].begin(),ord[i].end());
    }

    void rebuild(int x)
    {
        int r=(bel[n]==x)?n:(x*bsz);
        ord[x].clear();
        for(int i=(x-1)*bsz+1;i<=r;i++)
            ord[x].pb(a[i]);
        sort(ord[x].begin(),ord[x].end());
    }

    void add(int l,int r,ll val)
    {
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]+=val;
        rebuild(bel[l]);
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            ad[i]+=val;
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]+=val;
        rebuild(bel[r]);
    }

    int get_min(int l,int r,ll val)
    {
        int res=0;
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            if(a[i]+ad[bel[i]]<val)res++;
        if(bel[l]==bel[r])return res;
        for(int i=bel[l]+1;i<bel[r];i++)
            res+=lower_bound(ord[i].begin(),ord[i].end(),val-ad[i])-ord[i].begin();
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            if(a[i]+ad[bel[i]]<val)res++;
        return res;
    }

    void clear(){memset(ad,0,sizeof(ad));}
}b;
3.区间加, 查询区间内小于某个数的最大的元素

struct block
{
    static const int __=100005;
    static const int _b_=400;
    ll a[__];int n,bsz,bel[__];
    ll ad[_b_];
    vector<ll>ord[_b_];

    ll operator[](int x){return a[x]+ad[bel[x]];}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            ord[bel[i]=(i-1)/bsz+1].pb(a[i]);
        for(int i=1;i<=bel[n];i++)
            sort(ord[i].begin(),ord[i].end());
    }

    void rebuild(int x)
    {
        int r=(bel[n]==x)?n:(x*bsz);
        ord[x].clear();
        for(int i=(x-1)*bsz+1;i<=r;i++)
            ord[x].pb(a[i]);
        sort(ord[x].begin(),ord[x].end());
    }

    void add(int l,int r,ll val)
    {
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]+=val;
        rebuild(bel[l]);
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            ad[i]+=val;
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]+=val;
        rebuild(bel[r]);
    }

    int get_pre(int l,int r,ll val)
    {
        ll res=-1;
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            if(a[i]+ad[bel[i]]<val)
                res=max(res,a[i]+ad[bel[i]]);
        if(bel[l]==bel[r])return res;
        for(int i=bel[l]+1;i<bel[r];i++)
        {
            int x=lower_bound(ord[i].begin(),ord[i].end(),val-ad[i])-ord[i].begin();
            if(x)res=max(res,ord[i][x-1]+ad[i]);
        }
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            if(a[i]+ad[bel[i]]<val)
                res=max(res,a[i]+ad[bel[i]]);
        return res;
    }

    void clear(){memset(ad,0,sizeof(ad));}
}b;
4.区间加, 查询区间和
struct block
{
    static const int __=100005;
    static const int _b_=400;
    ll a[__];int n,bsz,bel[__];
    ll ad[_b_],sum[_b_];

    ll operator[](int x){return a[x]+ad[bel[x]];}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            sum[bel[i]=(i-1)/bsz+1]+=a[i];
    }

    void add(int l,int r,ll val)
    {
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]+=val,sum[bel[i]]+=val;
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            ad[i]+=val;
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]+=val,sum[bel[i]]+=val;
    }

    ll get_sum(int l,int r,ll mod)
    {
        ll res=0;
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            res=(res+a[i]+ad[bel[i]])%mod;
        if(bel[l]==bel[r])return res;
        for(int i=bel[l]+1;i<bel[r];i++)
            res=(res+sum[i]+ad[i]*bsz)%mod;
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            res=(res+a[i]+ad[bel[i]])%mod;
        return res;
    }

    void clear(){memset(ad,0,sizeof(ad));}
}b;
5.区间开方, 查询区间和
struct block
{
    static const int __=100005;
    static const int _b_=400;
    ll a[__];int n,bsz,bel[__];
    ll sum[_b_];bool all_one[_b_];

    ll operator[](int x){return a[x];}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            sum[bel[i]=(i-1)/bsz+1]+=a[i];
    }

    void sqt(int l,int r)
    {
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
        {
            int x=(int)sqrt(a[i]);
            sum[bel[i]]+=x-a[i],a[i]=x;
        }
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
        {
            if(all_one[i])continue;
            int maxx=0;
            for(int j=(i-1)*bsz+1;j<=i*bsz;j++)
            {
                int x=(int)sqrt(a[j]);
                sum[i]+=x-a[j],a[j]=x;
                maxx=max(maxx,x);
            }
            if(maxx==1)all_one[i]=true;
        }
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
        {
            int x=(int)sqrt(a[i]);
            sum[bel[i]]+=x-a[i],a[i]=x;
        }
    }

    ll get_sum(int l,int r)
    {
        ll res=0;
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            res+=a[i];
        if(bel[l]==bel[r])return res;
        for(int i=bel[l]+1;i<bel[r];i++)
            res+=sum[i];
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            res+=a[i];
        return res;
    }
}b;
6.单点插入, 查询单点值
struct block
{
    static const int __=200005;
    static const int _b_=1000;
    int a[__];
    vector<int>blo[_b_];
    int n,bsz,bel[__];

    int operator[](int x)
    {
        int idx=1;
        for(;x>blo[idx].size();idx++)
            x-=blo[idx].size();
        return blo[idx][x-1];
    }

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            blo[bel[i]=(i-1)/bsz+1].pb(a[i]);
    }

    void rebuild()
    {
        n=0;
        for(int i=1;blo[i].size();blo[i++].clear())
            for(int j=0;j<blo[i].size();j++)
                a[++n]=blo[i][j];
        build();
    }

    void insrt(int x,int val)
    {
        int idx=1;
        for(;x>blo[idx].size();idx++)
            x-=blo[idx].size();
        blo[idx].insert(blo[idx].begin()+x-1,val);
        if(blo[idx].size()>bsz*17)
            rebuild();
    }

}b;
7.区间加法.乘法, 查询单点值
struct block
{
    static const int __=100005;
    static const int _b_=400;
    ll a[__],ad[_b_],mu[_b_];
    int n,bsz,bel[__];

    ll operator[](int x){return (a[x]*mu[bel[x]]+ad[bel[x]]);}

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            bel[i]=(i-1)/bsz+1;
        for(int i=1;i<=bel[n];i++)
            mu[i]=1,ad[i]=0;
    }

    void pushdown(int x)
    {
        if(mu[x]==1 && ad[x]==0)return;
        for(int i=(x-1)*bsz+1;i<=x*bsz;i++)
            a[i]=(a[i]*mu[x]+ad[x])%10007;
        mu[x]=1,ad[x]=0;
    }

    void add(int l,int r,ll val)
    {
        pushdown(bel[l]);
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]=(a[i]+val)%10007;
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            ad[i]=(ad[i]+val)%10007;
        pushdown(bel[r]);
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]=(a[i]+val)%10007;
    }

    void mul(int l,int r,ll val)
    {
        pushdown(bel[l]);
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            a[i]=a[i]*val%10007;
        if(bel[l]==bel[r])return;
        for(int i=bel[l]+1;i<bel[r];i++)
            mu[i]=mu[i]*val%10007,
            ad[i]=ad[i]*val%10007;
        pushdown(bel[r]);
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            a[i]=a[i]*val%10007;
    }
}b;
8.区间覆盖, 查询区间内等于某个数的个数

struct block
{
    static const int __=100005;
    static const int _b_=400;
    ll a[__],st[_b_];
    bool same[_b_];
    int n,bsz,bel[__];

    void build()
    {
        bsz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
            bel[i]=(i-1)/bsz+1;
    }

    void pushdown(int x)
    {
        if(!same[x])return;
        int r=(bel[n]==x)?n:(x*bsz);
        for(int i=(x-1)*bsz+1;i<=r;i++)
            a[i]=st[x];
        same[x]=false;
    }

    int set(int l,int r,ll val)
    {
        int res=0;
        pushdown(bel[l]);
        for(int i=l;i<=min(r,bel[l]*bsz);i++)
            if(a[i]==val)res++;
            else a[i]=val;
        if(bel[l]==bel[r])return res;
        for(int i=bel[l]+1;i<bel[r];i++)
            if(same[i])
                if(st[i]==val)res+=bsz;
                else st[i]=val;
            else
            {
                for(int j=(i-1)*bsz+1;j<=i*bsz;j++)
                    if(a[j]==val)res++;
                    else a[j]=val;
                same[i]=true,st[i]=val;
            }
        pushdown(bel[r]);
        for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
            if(a[i]==val)res++;
            else a[i]=val;
        return res;
    }
}b;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值