LOJ-6277-数列分块入门1(分块)

链接:

https://loj.ac/problem/6277

题意:

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

思路:

线段树可以解决,用来学习分块.
分块概念就是,将序列分为sqrt(n)块,每次区间操作在满足一个快时操作块,最多sqrt(n)块, 处于边界时,直接对边界暴力操作,复杂度最多sqrt(n).

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
//#include <memory.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <stack>
#include <string>
#include <assert.h>
#include <iomanip>
#define MINF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 5e4+10;

int a[MAXN], Tag[MAXN];
int Rank[MAXN];
int n, part;

void Update(int l, int r, int c)
{
    for (int i = l;i <= min(r, Rank[l]*part);i++)
        a[i] += c;
    if (Rank[l] != Rank[r])
    {
        for (int i = (Rank[r]-1)*part+1;i <= r;i++)
            a[i] += c;
    }
    for (int i = Rank[l]+1;i <= Rank[r]-1;i++)
        Tag[i] += c;
}

int main()
{
    scanf("%d", &n);
    part = sqrt(n);
    for (int i = 1;i <= n;i++)
        scanf("%d", &a[i]);
    for (int i = 1;i <= n;i++)
        Rank[i] = (i-1)/part+1;
    int op, l, r, c;
    for (int i = 1;i <= n;i++)
    {
        scanf("%d %d %d %d", &op, &l, &r, &c);
        if (op == 0)
            Update(l, r, c);
        else
            printf("%d
", a[r]+Tag[Rank[r]]);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/YDDDD/p/11394588.html