分块板子求调!悬赏1关注

P3372 【模板】线段树 1

刘辰雨 @ 2022-12-06 21:58:41

rt

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

#define maxn 100005
using namespace std;

long long N,Q;
long long Tmp,Num;
long long V[maxn];
long long L[maxn],R[maxn],Sum[maxn],Lazy[maxn],Pos[maxn];

long long pos,Left,Right,Value;
long long Answer;

int main()
{
    scanf("%lld%lld",&N,&Q);
    for(long long i = 1 ; i<= N ; i++)
        scanf("%lld",&V[i]);
    Tmp = sqrt(N);
    Num = (N-1)/Tmp+1;
    for(long long i = 1 ; i<= N ; i++)
    {
        Pos[i] = (i-1)/Tmp+1;
        Sum[Pos[i]] += V[i];
        if(Pos[i] != Pos[i-1]) L[Pos[i]] = i, R[Pos[i-1]] = i-1;
    }
    R[Num] = N;
    while(Q--)
    {
        scanf("%lld%lld%lld",&pos,&Left,&Right);
        if(pos == 1)
        {
            scanf("%lld",&Value);
            if(Pos[Left] == Pos[Right])
            {
                for(long long i = Left ; i <= Right ; i++)
                    V[i] += Value;
                Sum[Pos[Left]] += Value*(Right-Left+1);
            }
            else
            {
                for(long long i = Pos[Left]+1 ; i< Pos[Right] ; i++)
                    Lazy[i] += Value, Sum[i] += (R[i]-L[i]+1)*Value;
                for(long long i = Left ; i<= R[Pos[Left]] ; i++)
                    V[i] += Value;
                Sum[Pos[Left]] += Value*(R[Pos[Left]]-Left+1);
                for(long long i = L[Pos[Right]] ; i<= Right ; i++)
                    V[i] += Value;
                Sum[Pos[Right]] += Value*(Right-L[Pos[Right]]+1);
            }
        }
        else
        {
            Answer = 0;
            if(Pos[Left] == Pos[Right])
            {
                for(long long i = Left ; i<= Right ; i++)
                    Answer += V[i];
                Answer += Lazy[Pos[Left]]*(Right-Left+1);
            }
            else
            {
                for(long long i = Pos[Left]+1 ; i< Pos[Right] ; i++)
                    Answer += Sum[i] + Lazy[i]*(R[i]-L[i]+1);
                for(long long i = Left ; i<= R[Pos[Left]] ; i++)
                    Answer += V[i];
                Answer += Lazy[Pos[Left]]*(R[Pos[Left]]-Left+1);
                for(long long i = L[Pos[Right]] ; i<= Right ; i++)
                    Answer += V[i];
                Answer += Lazy[Pos[Right]]*(Right-L[Pos[Right]]+1); 
            }
            printf("%lld\n",Answer);
        }
    }
    return 0;
}

by bamboo12345 @ 2022-12-06 22:01:21

@刘辰雨 你在加sum的时候已经加过一遍lazy了吧,计算答案的时候不用再加lazy了吧


by 刘辰雨 @ 2022-12-07 18:51:30

@bamboo123

并不呐,分三段分别加了 Lazy ,

\sum^{Left}_{i=R_{Pos_{Left}}}Lazy_{Pos_{Left}} \mathcal{+} \sum^{Pos_{Right}}_{i=Pos_{Left}+1}Lazy_i \times (R_i-L_i) \mathcal{+} \sum^{L_{Pos_{Right}}}_{i=Right} Lazy_{Pos_{Right}}

不重复的。


by bamboo12345 @ 2022-12-07 19:46:29

@刘辰雨 不是,你中间整块的你又加sum又加lazy会加两边的


by 刘辰雨 @ 2022-12-07 20:16:27

@bamboo123

A了,谢谢您


|