1. 程式人生 > >NBUT校賽 J Alex’s Foolish Function(分塊+延遲標記)

NBUT校賽 J Alex’s Foolish Function(分塊+延遲標記)

not unit itl 標記 ccf 一次 pan -s foo

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
l + 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(分塊+延遲標記)