LOJ-6280-数列分块入门4

链接:

https://loj.ac/problem/6280

题意:

给出一个长为n 的数列,以及 n个操作,操作涉及区间加法,区间求和。

思路:

sum维护区间和, tag维护每个区间多加的,不是一整块的暴力加进去,算的时候加上tag即可.

代码:

#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 = 1e5+10;

LL a[MAXN], Tag[MAXN], Sum[MAXN];
LL Belong[MAXN];
int n, part;

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

LL Query(LL l, LL r, LL c)
{
    LL res = 0;
    for (int i = l;i <= min(Belong[l]*part, r);i++)
        res += (a[i]+Tag[Belong[i]]);
    if (Belong[l] != Belong[r])
    {
        for (int i = max((Belong[r]-1)*part+1, l);i <= r;i++)
            res += (a[i]+Tag[Belong[i]]);
    }
    for (int i = Belong[l]+1;i <= Belong[r]-1;i++)
        res += (Sum[i]+Tag[i]*part);
    return res%(c+1);
}

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

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