数列分块入门 1

题目描述

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

输入格式

第一行输入一个数字 n。

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

接下来输入 n 行询问,每行输入四个数字 opt、l、r、c,以空格隔开。

若 opt==0,表示将位于[l,r] 的之间的数字都加 c 。

若 opt==1,表示询问 ar 的值(l 和 c忽略)。

输出格式

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

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include <sstream>
#include<vector>
#include<cmath>    
#include<stack>
#include<random>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define LD long double
#define LL long long
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define inf 1<<30
#define  ull unsigned long long
const int Mod = 998244353;
const int maxn = 1e6 + 5;
int read()
{
    int x = 0, f = 1; char ch = getchar();
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
int n,opt,l,r,c,block,num;
LL L[maxn],R[maxn],belong[maxn],change[maxn];
LL a[maxn];
void build()
{
    block=sqrt(n);//分块操作,每一个块的大小为sqrt(n)
    num=n/block;//一共分成num个块
    if(n%block)num++;//如果有剩,num+1
    for(int i=1;i<=num;i++){
        L[i]=(i-1)*block+1;  //第i个块的左边界
        R[i]=i*block;        //第i个块的右边界
    }
    R[num]=n;    //第num个块的右边界为n
    for(int i=1;i<=n;i++){        //遍历n个数
        belong[i]=(i-1)/block+1;//确定第i个数属于第几个块
    }
}
void add(int x,int y,int val)
{
    if(belong[x]==belong[y]){//如果x和y属于同一个块
        for(int i=x;i<=y;i++){//直接遍历就好,因为一个块的大小最多为sqrt(n)
            a[i]+=val;
        }
    }
    else{
        for(int i=x;i<=R[belong[x]];i++){//遍历这个块的[x ,块的右边界]
            a[i]+=val;
        }
        for(int i=belong[x]+1;i<belong[y];i++){//遍历[x+1,y-1]的块,直接改变块的整体
            change[i]+=val;
        }
        for(int i=L[belong[y]];i<=y;i++){//遍历这个块的[块的左边界,y]
            a[i]+=val;
        }
    }
}
int main(){
    io;
    n=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    build();//分块
    for(int i=1;i<=n;i++){
        opt=read();l=read();r=read();c=read();
        if(opt==0){
            add(l,r,c);
        }
        else{
            printf("%lld\n",a[r]+change[belong[r]]);
        }
    }
    return 0;
}

 

 

posted @ 2021-03-15 20:30  夜灯长明  阅读(84)  评论(0编辑  收藏  举报