[树状数组] Codeforces 1406D Three Sequences

题目大意

给定一个序列 (a_1,a_2,dots,a_n),要求构造出长度为 (n) 的序列 ({b_n},{c_n}),满足 (a_i=b_i+c_i),并且 ({b_n}) 是不下降序列,({c_n}) 是不上升序列。有 (q) 次操作,每次操作可以把 ([l,r]) 的数增加 (x),求每次操作后最小的 (max{b_i,c_i})
((n,qleq 10^5))

题解

考虑构造 ({a_n},{b_n},{c_n}) 的差分序列 (Delta a_i=a_{i+1}-a_i,Delta b_i=b_{i+1}-b_i,Delta c_i=c_{i+1}-c_i),那么有 (Delta b_igeq 0,Delta c_ileq 0,Delta a_i=Delta b_i+Delta c_i)

因为要最小化 (max{b_i,c_i}),当 (Delta a_i>0) 时,令 (Delta b_i=Delta a_i,Delta c_i=0)。当 (Delta a_ileq 0) 时,令 (Delta b_i=0,Delta c_i=Delta a_i)。显然这样是最优的,因为当 (Delta a_i>0) 时,若 (Delta b_i<Delta a_i),则 (Delta c_i>0),不满足;若 (Delta b_i>Delta a_i),则 (Delta c_i<0),此时比 (Delta b_i=Delta a_i) 更劣。

那么假设我们已经确定了 (b_1)(c_1),则 (b_n=b_1+sum_{i=1}^{n-1}Delta b_i)。因为 ({b_n}) 不降, ({c_n}) 不升,所以 (max{b_i,c_i}=max{b_n,c_1}=max{b_1+sum_{i=1}^{n-1}Delta b_i,c_1})。我们肯定是希望 (b_n)(c_1) 越接近越好,因为 (sum_{i=1}^{n-1} Delta b_i) 是固定的,所以我们可以通过将 ({b_n})({c_n}) 分别整体平移来使得 (b_n)(c_1) 更接近,所以 (max{b_i,c_i}=leftlceil frac{b_n+c_1}{2} ight ceil=leftlceil frac{b_1+sum_{i=1}^{n-1}Delta b_i+c_1}{2} ight ceil=leftlceil frac{a_1+sum_{i=1}^{n-1}Delta b_i}{2} ight ceil)

对于 (sum_{i=1}^{n-1}Delta b_i),我们可以通过预处理求出,对于将区间 ([l,r]) 加上 (x),因为我们做了差分,只需要修改左右两个端点对 (Delta b_i) 造成的影响即可,然后还要求每次修改后的 (sum_{i=1}^{n-1}Delta b_i),于是可以使用树状数组来维护,时间复杂度 (O(n log n))

Code

#include <bits/stdc++.h>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

inline int lowbit(int x){return x&(-x);}

LL a[100010],Delta[100010];
struct BIT{
    LL Node[100010];
    int N;
    void set_Len(int len){N=len;}
    void Update(int x,LL Add){for(;x<=N;x+=lowbit(x)) Node[x]+=Add;}
    LL PrefixSum(int x){LL Res=0;for(;x;x-=lowbit(x)) Res+=Node[x];return Res;}
    LL Query(int L,int R){return PrefixSum(R)-PrefixSum(L-1);}
    LL GetAns(){
        LL Res=a[1]+PrefixSum(N);
        return (Res&1)?((Res>>1)+1):(Res>>1);
    }
};
BIT Tree;
int N,M;

int main(){
    Read(N);
    Tree.set_Len(N-1);
    for(RG i=1;i<=N;++i)
        Read(a[i]);
    for(RG i=1;i<N;++i){
        if(a[i+1]-a[i]>0) Tree.Update(i,a[i+1]-a[i]);
        Delta[i]=a[i+1]-a[i];
    }
    printf("%I64d
",Tree.GetAns());
    Read(M);
    while(M--){
        int L,R;LL Add;
        Read(L);Read(R);Read(Add);
        if(L==1) a[1]+=Add;
        if(L>1){
            Delta[L-1]+=Add;
            Tree.Update(L-1,-Tree.Query(L-1,L-1));
            if(Delta[L-1]>0) Tree.Update(L-1,Delta[L-1]);  
        }
        if(R<N){
            Delta[R]-=Add;
            Tree.Update(R,-Tree.Query(R,R));
            if(Delta[R]>0) Tree.Update(R,Delta[R]);  
        }
        printf("%I64d
",Tree.GetAns());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AEMShana/p/13896255.html