数组分块1

板子题 https://loj.ac/problem/6277

题目大意是 对于一个长度为n的数组进行区间操作和单点询问。 

单点询问相对比较简单,数组简单存储之后就可以O(1)输出。

 主要就是对于区间修改:

分块之后,对于需要修改的L~R的区间,可以简单分情况讨论:

1.L和R属于同一个块

2.L和R不属于同一个块

#include<bits/stdc++.h>
using namespace std;
#define maxn 50010
int a[maxn],belong[maxn],l[maxn],r[maxn],lazy[maxn],block,num,n;
void build()
{
    memset(lazy,0,sizeof(lazy));
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=num;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    for(int i=1;i<=n;i++)
        belong[i]=(i-1)/block+1;
}
void update(int left,int right,int c)
{
    if(belong[left]==belong[right])
        for(int i=left;i<=right;i++)
            a[i]+=c;
    else
    {
        for(int i=left;i<=r[belong[left]];i++)
            a[i]+=c;
        for(int i=l[belong[right]];i<=right;i++)
            a[i]+=c;
        for(int i=belong[left]+1;i<=belong[right]-1;i++)
            lazy[i]+=c;
    }

}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    build();
    for(int i=1;i<=n;i++)
    {
        int opt,left,right,c;
        cin>>opt>>left>>right>>c;
        if(!opt)
            update(left,right,c);
        else
            cout<<a[right]+lazy[belong[right]]<<endl;
    }
    return 0;

}

 

posted @ 2018-08-20 22:19  eason99  阅读(83)  评论(0编辑  收藏  举报