NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)

Posted Blackops

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)相关的知识,希望对你有一定的参考价值。

Problem J: Alex’s Foolish Function

Time Limit: 8 Sec  Memory Limit: 128 MB
Submit: 18  Solved: 2

Description

Alex has an array F which size is n, initially each element’s value is zero. Now he wants to operate the array, he has 4 different functions:
1) Function A(l, r):
Add the elements between l to r (inclusive) where the i
th add i - l + 1, for instance, if l is 4,
r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 4 6 13.
2) Function B(l, r):
Add the elements between l to r (inclusive) where the i
th add r - i + 1, for instance, if l is 4,
r is 6 and the elements between 4 to 6 is 3 4 10, after this operation, these elements will become 6 6 11.
3) Function C(l, r, x):
Set all the elements(between l to r) to x, for instance, if l is 4, r is 6 and the elements
between 4 to 6 is 3 4 10, and x = 2, after this operation, these elements will become 2 2 2.
4) Function S(l, r):
Output F
+ Fl+1 + Fl+2 + ...+ Fr

 

Input

Input start with an integer T(1 <= T <= 5), denoting the number of test case.
For each test case, first line contains n, m (1 <= n <= 200000, 1 <= m <= 100000), denoting the array’size and the number of operations.
Next m lines, each line contains an operation, formatting as
A l r
B l r
C l r x
S l r 

 

Output

For each S Function operations, output the sum. 

 

Sample Input

1
5 4
A 1 3
B 2 5
C 1 1 2
S 1 5

Sample Output

17

 

 

正规做法是线段树维护区间的左加、右加或者覆盖信息,然而想用分块写一写。

对于A操作,每一个块维护起始的加数,以及A操作的次数,

对于B操作,每一个块维护末尾的加数,以及B操作的次数,

对于C操作,每一个块维护准备覆盖的值val。

显然对于A操作和B操作维护的信息,是满足区间加法的,即[1,4]A操作一次,[2,4]A操作一次,比如当前块是[2,4],记为Bx,那么我们可以记录起始的加数:(2-1+1)+(2-2+1)=3,A操作次数为2,即arr[2]+=3,arr[3]+=(3+2),arr[4]+=(3+2+2),然后我们可以发现这是一个等差数列,可以用公式快速得到有延迟标记A操作的区间和,即$(Bx.lazy_A+(Bx.lazy_A+Bx.len-1))*Bx.len/2+Bx.sum$,然后B操作也同理,最后加上本身的$Bx.sum$即可(这里要注意AB操作不能重复加Bx.sum);B操作同理;C操作的话由于是覆盖那么在更新的时候把更新到的块的$lazy_c$更新,并把$lazy_A$与$lazy_B$取消掉即可,由于可能$lazy_c$为0,初始值应设为一个不太可能用到的数,比如$-INF$。

代码:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 200010;
const int M = 450;
struct Block
{
    int l, r;
    LL lazy1, lazy2, lazy3, sum;
    LL c1, c2;

    inline int len()
    {
        return r - l + 1;
    }
};
Block B[M];
LL arr[N];
int belong[N], unit, bcnt;
int n, m;

void init()
{
    int i;
    unit = sqrt(n);
    bcnt = n / unit;
    if (n % unit)
        ++bcnt;
    for (i = 1; i <= bcnt; ++i)
    {
        B[i].l = (i - 1) * unit + 1;
        B[i].r = i * unit;
        B[i].sum = 0LL;
        B[i].lazy1 = 0LL;
        B[i].lazy2 = 0LL;
        B[i].lazy3 = -INF;
        B[i].c1 = B[i].c2 = 0LL;
    }
    B[bcnt].r = n;
    for (i = 1; i <= n; ++i)
    {
        arr[i] = 0LL;
        belong[i] = (i - 1) / unit + 1;
    }
}
void pushdown(int bx)
{
    if (B[bx].lazy3 != -INF)
    {
        for (int i = B[bx].l; i <= B[bx].r; ++i)
            arr[i] = B[bx].lazy3;
        B[bx].lazy3 = -INF;
    }
    if (B[bx].lazy1)
    {
        for (int i = B[bx].l; i <= B[bx].r; ++i)
        {
            arr[i] += + B[bx].lazy1;
            B[bx].lazy1 += B[bx].c1;
        }
        B[bx].lazy1 = 0LL;
        B[bx].c1 = 0LL;
    }
    if (B[bx].lazy2)
    {
        for (int i = B[bx].r; i >= B[bx].l; --i)
        {
            arr[i] += + B[bx].lazy2;
            B[bx].lazy2 += B[bx].c2;
        }
        B[bx].lazy2 = 0LL;
        B[bx].c2 = 0LL;
    }
    B[bx].sum = 0LL;
    for (int i = B[bx].l; i <= B[bx].r; ++i)
        B[bx].sum += arr[i];
}
void update(int l, int r, int ops, LL val = 0LL)
{
    int bl = belong[l], br = belong[r];
    int i;
    if (bl == br)
    {
        pushdown(bl);
        if (ops == 1)
        {
            for (i = l; i <= r; ++i)
            {
                B[bl].sum -= arr[i];
                arr[i] = arr[i] + (LL)(i - l + 1LL);
                B[bl].sum += arr[i];
            }
        }
        else if (ops == 2)
        {
            for (i = r; i >= l; --i)
            {
                B[bl].sum -= arr[i];
                arr[i] = arr[i] + (LL)(r - i + 1LL);
                B[bl].sum += arr[i];
            }
        }
        else if (ops == 3)
        {
            for (i = l; i <= r; ++i)
            {
                B[bl].sum -= arr[i];
                arr[i] = val;
                B[bl].sum += arr[i];
            }
        }
    }
    else
    {
        //left
        pushdown(bl);
        if (ops == 1)
        {
            for (i = l; i <= B[bl].r; ++i)
            {
                B[bl].sum -= arr[i];
                arr[i] = arr[i] + (LL)(i - l + 1LL);
                B[bl].sum += arr[i];
            }
        }
        else if (ops == 2)
        {
            for (i = B[bl].r; i >= l; --i)
            {
                B[bl].sum -= arr[i];
                arr[i] = arr[i] + (LL)(r - i + 1LL);
                B[bl].sum += arr[i];
            }
        }
        else if (ops == 3)
        {
            for (i = l; i <= B[bl].r; ++i)
            {
                B[bl].sum -= arr[i];
                arr[i] = val;
                B[bl].sum += arr[i];
            }
        }
        //right
        pushdown(br);
        if (ops == 1)
        {
            for (i = B[br].l; i <= r; ++i)
            {
                B[br].sum -= arr[i];
                arr[i] = arr[i] + (LL)(i - l + 1LL);
                B[br].sum += arr[i];
            }
        }
        else if (ops == 2)
        {
            for (i = r; i >= B[br].l; --i)
            {
                B[br].sum -= arr[i];
                arr[i] = arr[i] + (LL)(r - i + 1LL);
                B[br].sum += arr[i];
            }
        }
        else if (ops == 3)
        {
            for (i = B[br].l; i <= r; ++i)
            {
                B[br].sum -= arr[i];
                arr[i] = val;
                B[br].sum += arr[i];
            }
        }
        for (i = bl + 1; i < br; ++i)
        {
            if (ops == 3)
            {
                B[i].lazy3 = val;
                B[i].c1 = 0LL;
                B[i].c2 = 0LL;
                B[i].lazy1 = 0LL;
                B[i].lazy2 = 0LL;
            }
            else if (ops == 2)
            {
                B[i].lazy2 += (LL)(r - B[i].r + 1LL);
                ++B[i].c2;
            }
            else if (ops == 1)
            {
                B[i].lazy1 += (LL)(B[i].l - l + 1LL);
                ++B[i].c1;
            }
        }
    }
}
LL query(int l, int r)
{
    int bl = belong[l], br = belong[r], i;
    LL sum = 0LL;
    if (bl == br)
    {
        pushdown(bl);
        for (i = l; i <= r; ++i)
            sum += arr[i];
        return sum;
    }
    else
    {
        pushdown(bl);
        pushdown(br);
        for (i = l; i <= B[bl].r; ++i)
            sum += arr[i];
        for (i = B[br].l; i <= r; ++i)
            sum += arr[i];
        for (i = bl + 1; i < br; ++i)
        {
            if (B[i].lazy3 != -INF)
                sum += (LL)B[i].len() * B[i].lazy3;
            if (B[i].lazy1)
                sum += (B[i].lazy1 + B[i].lazy1 + (LL)(B[i].len() - 1LL) * B[i].c1) * (LL)B[i].len() / 2LL;
            if (B[i].lazy2)
                sum += (B[i].lazy2 + B[i].lazy2 + (LL)(B[i].len() - 1LL) * B[i].c2) * (LL)B[i].len() / 2LL;
            if (B[i].lazy3 == -INF)
                sum += B[i].sum;
        }
        return sum;
    }
}
int main(void)
{
    // fin("test0.in");
    // fout("data_wa.txt");
    int tcase, l, r, v;
    char ops[4];
    scanf("%d", &tcase);
    while (tcase--)
    {
        scanf("%d%d", &n, &m);
        init();
        while (m--)
        {
            scanf("%s", ops);
            if (ops[0] == ‘A‘)
            {
                scanf("%d%d", &l, &r);
                update(l, r, 1);
            }
            else if (ops[0] == ‘B‘)
            {
                scanf("%d%d", &l, &r);
                update(l, r, 2);
            }
            else if (ops[0] == ‘C‘)
            {
                scanf("%d%d%d", &l, &r, &v);
                update(l, r, 3, (LL)v);
            }
            else
            {
                scanf("%d%d", &l, &r);
                printf("%lld\n", query(l, r));
            }
        }
    }
    return 0;
}

以上是关于NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)的主要内容,如果未能解决你的问题,请参考以下文章

南昌大学航天杯第二届程序设计竞赛校赛网络同步赛 F

北邮校赛 F. Gabriel's Pocket Money(树状数组)

NBUT 1221 Intermediary

2020武大校赛记录

HDU校赛 | 2019 Multi-University Training Contest 3

CF1097F Alex and a TV Show