数列分块九讲板子(封装)

第一讲:区间加减,单点查询

复杂度:O(n\sqrt n)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    vector<int> a,block,tag;
    vector<vector<int> > ve;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5,0),ve(n2+5)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
        {
            block[i]=(i-1)/blo+1;
            ve[block[i]].push_back(a[i]);
        }
    }
    void add(int l,int r,int x)
    {
        for(int i=l;i<=min(block[l]*blo,r);i++)
            a[i]+=x;
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                a[i]+=x;
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            tag[i]+=x;
    }
    int query(int x)
    {
        return a[x]+tag[block[x]];
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(n--)
    {
        int nb,l,r,c;
        l++;
        r++;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.add(l,r,c);
        else
            cout<<fk1.query(r)<<endl;
    }
    return 0;
}

第二讲:区间加减,查询区间内小于x的数的个数 

复杂度:O(n\sqrt n log\sqrt n+nlogn)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    vector<int> a,block,tag;
    vector<vector<int> > ve;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5),ve(n2+5)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
        {
            block[i]=(i-1)/blo+1;
            ve[block[i]].push_back(a[i]);
        }
        for(int i=1;i<=block[nn];i++)
            sort(ve[i].begin(),ve[i].end());
    }
    void reset(int x)
    {
        ve[x].clear();
        for(int i=(x-1)*blo+1;i<=min(x*blo,n1);i++)
            ve[x].push_back(a[i]);
        sort(ve[x].begin(),ve[x].end());
    }
    void add(int l,int r,int x)
    {
        for(int i=l;i<=min(block[l]*blo,r);i++)
            a[i]+=x;
        reset(block[l]);
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                a[i]+=x;
            reset(block[r]);
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            tag[i]+=x;
    }
    int query(int l,int r,int c)
    {
        int ans=0;
        for(int i=l;i<=min(block[l]*blo,r);i++)
        {
            if(a[i]+tag[block[l]]<c)
                ans++;
        }
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                if(a[i]+tag[block[r]]<c)
                    ans++;
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
        {
            int x=c-tag[i];
            ans+=lower_bound(ve[i].begin(),ve[i].end(),x)-ve[i].begin();
        }
        return ans;
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;k=n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(k--)
    {
        int nb,l,r,c;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.add(l,r,c);
        else
            cout<<fk1.query(l,r,c*c)<<endl;
    }
    return 0;
}

第三讲:区间加减 ,找x的前驱(区间内比x小的最大元素)

 复杂度:O(n\sqrt n log\sqrt n+nlogn)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    vector<int> a,block,tag;
    vector<vector<int> > ve;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5),ve(n2+5)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
        {
            block[i]=(i-1)/blo+1;
            ve[block[i]].push_back(a[i]);
        }
        for(int i=1;i<=block[nn];i++)
            sort(ve[i].begin(),ve[i].end());
    }
    void reset(int x)
    {
        ve[x].clear();
        for(int i=(x-1)*blo+1;i<=min(x*blo,n1);i++)
            ve[x].push_back(a[i]);
        sort(ve[x].begin(),ve[x].end());
    }
    void add(int l,int r,int x)
    {
        for(int i=l;i<=min(block[l]*blo,r);i++)
            a[i]+=x;
        reset(block[l]);
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                a[i]+=x;
            reset(block[r]);
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            tag[i]+=x;
    }
    int query(int l,int r,int c)
    {
        int ans=-inf*inf;
        for(int i=l;i<=min(block[l]*blo,r);i++)
        {
            if(a[i]+tag[block[l]]<c)
                ans=max(ans,a[i]+tag[block[l]]);
        }
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                if(a[i]+tag[block[r]]<c)
                    ans=max(ans,a[i]+tag[block[r]]);
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
        {
            int x=c-tag[i];
            auto it=lower_bound(ve[i].begin(),ve[i].end(),x);//找到块中第一个大于等于x的值
            if(it!=ve[i].begin())
            {
                it--;
                ans=max(ans,*it+tag[i]);//这里要加上tag[i]
            }
        }
        if(ans!=-inf*inf)
            return ans;
        else
            return -1;
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;k=n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(k--)
    {
        int nb,l,r,c;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.add(l,r,c);
        else
            cout<<fk1.query(l,r,c)<<endl;
    }
    return 0;
}

第四讲:区间加减,区间求和并模(c+1)

 复杂度:O(n\sqrt n)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    vector<int> a,block,tag,sum;
    vector<vector<int> > ve;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),tag(nn+5,0),sum(nn+5,0),ve(n2+5)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
        {
            block[i]=(i-1)/blo+1;
            sum[block[i]]+=a[i];
        }
    }
    void add(int l,int r,int x)
    {
        for(int i=l;i<=min(block[l]*blo,r);i++)
        {
            a[i]+=x;
            sum[block[i]]+=x;
        }
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
            {
                a[i]+=x;
                sum[block[i]]+=x;
            }
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
        {
            tag[i]+=x;
            sum[i]+=x*blo;
        }
    }
    int query(int l,int r,int c)
    {
        int ans=0;
        for(int i=l;i<=min(block[l]*blo,r);i++)
            ans=(ans+a[i]+tag[block[i]])%c;
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                ans=(ans+a[i]+tag[block[i]])%c;
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            ans=(ans+sum[i])%c;
        return ((ans%c)+c)%c;
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(n--)
    {
        int nb,l,r,c;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.add(l,r,c);
        else
            cout<<fk1.query(l,r,c+1)<<endl;
    }
    return 0;
}

第五讲: 区间开方,区间求和

复杂度:(略)

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    vector<int> a,block,flag,sum;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),block(nn+5),flag(nn+5,0),sum(nn+5,0)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
        {
            block[i]=(i-1)/blo+1;
            sum[block[i]]+=a[i];
        }
    }
    void slove_sqrt(int x)
    {
        if(flag[x])
            return;
        flag[x]=1;
        sum[x]=0;
        for(int i=(x-1)*blo+1;i<=x*blo;i++)
        {
            a[i]=sqrt(a[i]);
            sum[x]+=a[i];
            if(a[i]>1)
                flag[x]=0;
        }
    }
    void add(int l,int r,int x)
    {
        for(int i=l;i<=min(block[l]*blo,r);i++)
        {
            sum[block[i]]-=a[i];
            a[i]=sqrt(a[i]);
            sum[block[i]]+=a[i];
        }
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
            {
                sum[block[i]]-=a[i];
                a[i]=sqrt(a[i]);
                sum[block[i]]+=a[i];
            }
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            slove_sqrt(i);
    }
    int query(int l,int r)
    {
        int ans=0;
        for(int i=l;i<=min(block[l]*blo,r);i++)
            ans+=a[i];
        if(block[l]!=block[r])
        {
            for(int i=(block[r]-1)*blo+1;i<=r;i++)
                ans+=a[i];
        }
        for(int i=block[l]+1;i<=block[r]-1;i++)
            ans+=sum[i];
        return ans;
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(n--)
    {
        int nb,l,r,c;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.add(l,r,c);
        else
            cout<<fk1.query(l,r)<<endl;
    }
    return 0;
}

第六讲:单点插入,单点查询

复杂度:(略)

/*
 author:wuzx
 */

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define endl "\n"
#define P pair<int,int>
#define f first
#define s second
using namespace std;
typedef unsigned long long ull;
const int maxn=200010;
const int inf=0x3f3f3f3f;
const int mod=998244353;
int t;
int n,m,k;
struct fenkuai{
    const int n1,blo;
    int mm;
    vector<int> a,st;
    vector<vector<int> > ve;
    fenkuai(int nn,vector<int> &a2,int n2):n1(nn),blo(n2),a(nn+5),st(nn*2+5),ve(n2*2+5)
    {
        for(int i=1;i<=nn;i++)
            a[i]=a2[i];
        for(int i=1;i<=nn;i++)
            ve[(i-1)/blo+1].push_back(a[i]);
        mm=(nn-1)/blo+1;
    }
    pair<int,int> query(int b)
    {
        int x=1;
        while(b>ve[x].size())
        {
            b-=ve[x].size();
            x++;
        }
        return make_pair(x,b-1);
    }
    void rebuild()
    {
        int top=0;
        for(int i=1;i<=mm;i++)
        {
            for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++)
                st[++top]=*j;
            ve[i].clear();
        }
        int blo2=sqrt(top);
        for(int i=1;i<=top;i++)
            ve[(i-1)/blo2+1].push_back(st[i]);
        m=(top-1)/blo2+1;
    }
    void insert(int idx,int x)
    {
        pair<int,int> tt=query(idx);
        ve[tt.f].insert(ve[tt.f].begin()+tt.s,x);
        if(ve[tt.f].size()>20*blo)
            rebuild();
    }
    int getnum(int idx)
    {
        pair<int,int> tt=query(idx);
        return ve[tt.f][tt.s];
    }
};
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;k=n;
    vector<int> a(n+5);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    fenkuai fk1(n,a,sqrt(n));
    while(k--)
    {
        int nb,l,r,c;
        cin>>nb>>l>>r>>c;
        if(nb==0)
            fk1.insert(l,r);
        else
            cout<<fk1.getnum(r)<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值