hzwer分块教程

这篇博客介绍了数列分块的算法概念,并通过多个样例输入和输出详细解析了分块的思想及其在处理数列问题中的应用。内容涵盖零散修改、整块修改和查询操作,以及不同情况下的处理策略。
摘要由CSDN通过智能技术生成

#6277. 数列分块入门 1
在这里插入图片描述
样例输入
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

样例输出
2
5

n<5e4 , -2^31 <=others, ans<=2^31-1

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define m(a,b) memset(a,b,sizeof a)
#define sld(a) scanf("%lld",&a)
#define en '\n'
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,N=5e4+5;
ll tag[230],a[N];
int bl[N],block;
void chanspan(int l,int r,int c)
{
   
    for(int i=l;i<=min(bl[l]*block,r);i++)
        a[i]+=c;
    if(bl[l]!=bl[r])
        for(int i=(bl[r]-1)*block+1;i<=r;i++)
            a[i]+=c;
    for(int i=bl[l]+1;i<=bl[r]-1;i++)
        tag[i]+=c;
}
int main()
{
   
    int n;scanf("%d",&n);block=sqrt(n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]),bl[i]=(i-1)/block+1;
    for(int i=1;i<=n;i++)
    {
   
        int f,l,r,c;scanf("%d%d%d%d",&f,&l,&r,&c);
        if(!f)
            chanspan(l,r,c);
        else
            printf("%lld\n",a[r]+tag[bl[r]]);
    }
}

#6278. 数列分块入门 2
在这里插入图片描述

样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2

样例输出
3
0
2

n<5e4 , -2^31 <=others, ans<=2^31-1

修改
零散:将a[i]修改,将其所在块儿的vec[bl[l]],vec[bl[r]]修改。vec[i].push_back(a[i]),不是a[i]+tag[i],因为查询的时候,查询c-tag[i]。
整块:直接修改tag[i].(i是第几块)。
查询
零散:遍历暴力查询, if(a[i]+tag[bl[l]]<c) if(a[i]+tag[bl[r]]<c) ++num;
整块:对该块的vec[i]二分lower_bound(c-tag[i])。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,N=5e4+5;
ll tag[230],a[N];
int bl[N],block,n;
vector<ll>vec[230];
void reset(int x)
{
   
    vec[x].clear();
    for(int i=(x-1)*block+1;i<=min(x*block,n);i++)
        vec[x].push_back(a[i]);
    sort(vec[x].begin(),vec[x].end());
}
void chanspan(int l,int r,int c)
{
   
    for(int i=l;i<=min(bl[l]*block,r);i++)
        a[i]+=c;
    reset(bl[l]);
    if(bl[l]!=bl[r])
    {
   
        for(int i=(bl[r]-1)*block+1;i<=r;i++)
            a[i]+=c;
        reset(bl[r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值