数列分块入门1 LibreOj 6277

题目描述

给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。

输入格式

第一行输入一个数字 。

第二行输入n个数字,第i个数字为a_i,以空格隔开。

接下来输入n行询问,每行输入四个数字oplrc,以空格隔开。

op=1,表示将位于[l,r]  的之间的数字都加c

op=0,表示询问 a_r的值(lr忽略)。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

InputOutput
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0
2
5

 代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N = 50007;
int l[N],r[N],block,num,belong[N],n,x,y;
ll a[N],lazy[N];
inline void build()
{
    block=sqrt(n);
    //block代表的是完整分块的长度
    num=n/block;if (n%num) num++;
    //num表示分块的块的个数
    for (int i=1;i<=num;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    //l[i],r[i]代表的是第i个块的左/右的a数组下标
    r[num]=n;
    //不完整块
    for (int i=1;i<=n;i++)
        belong[i]=(i-1)/block+1;
    //belong代表的是当前a[i]这个数是属于哪个块
}
inline void update(int x,int y,int c)
{
    if (belong[x]==belong[y])
    {
        for (int i=x;i<=y;i++) a[i]+=c;
        return;
    }
    //不特判这个if下面的第一个循环和第三个循环可能会重复
    for (int i=x;i<=r[belong[x]];i++) a[i]+=c;
    //暴力美学
    for (int i=belong[x]+1;i<belong[y];i++) lazy[i]+=c;
    //同线段树 lazy标记
    for (int i=l[belong[y]];i<=y;i++) a[i]+=c;
}
inline ll ask(int x)
{
    return a[x]+lazy[belong[x]];
    //还要加上lazy
}
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>n;
    for (int i=1;i<=n;i++)
        cin>>a[i];
    build();
    for (int k=1;k<=n;k++)
    {
        int l,r,op,c;
        cin>>op>>l>>r>>c;
        if (op==0)
            update(l,r,c);
        else 
            cout<<ask(r)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值