分块练习

同样是昨天老师讲课讲到的东西,很奇怪以前居然一点也没接触过分块
明明是自己做题太少了喂
于是刷了一下菊苣的分块专题

数列分块入门 1

题目链接
入门无脑题,然而WA了三四发因为把l写成1了,,,被自己气笑了都,,,
对1~n这个区间,按照根号n的长度分为几个区间。
在修改( l , r )区间时,分为两种情况。
1,这段区间在同一个小块内,那么暴力枚举l到r修改这个区间各个元素值即可
2,左右端点不在同一区间,那么把要修改的区间分为三块(或者两块,看中间有没有小块了)暴力修改左端点到左端点所在小块末端和右端点小块头到右端点,对于中间的小块只修改其op值(标记这个区间内的元素要修改但未修改)
输出时候就直接是a[i]+op[i]了。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=5e4+10;
#define pi   acos(-1.0)
#define INF   0x3f3f3f3f
#define mod   1000000009
#define endll printf("\n")
#define s1(a) scanf("%d",&a)
#define s2(a,b) scanf("%d %d",&a,&b)
#define mem(a,b) memset(a,b,sizeof(a))
#define s3(a,b,c) scanf("%d %d %d",&a,&b,&c)
int n,block;//区间长度
int a[MAXN];
int num[MAXN];//每个位置属于哪个块
int op[MAXN];//块上的操作数
void update(int l,int r,int c)
{
    for(int i=l;i<=min(num[l]*block,r);i++)
        a[i]+=c;
    if(num[l]!=num[r])
        for(int i=(num[r]-1)*block+1;i<=r;i++)
            a[i]+=c;
    for(int i=num[l]+1;i<=num[r]-1;i++)
        op[i]+=c;
}
int main()
{
    s1(n);
    mem(op,0);
    for(int i=1;i<=n;i++)
        s1(a[i]);
    block=sqrt(n);
    for(int i=1;i<=n;i++)
        num[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)
            printf("%d\n",a[r]+op[num[r]]);
        else
            update(l,r,c);
    }
    return 0;
}

数列分块入门 2

咕咕咕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值