2023NOIP A层联测32-meirin

给出两个长度为 n n n 的序列 a , b a,b a,b

q q q 次操作,每次格式如下

给出 l r k 将序列 b b b 区间 [ l , r ] [l,r] [l,r] 的值每个加上 k k k

每次操作结束后,查询:

∑ l = 1 n ∑ r = l n ( ∑ i = l r a i ) × ( ∑ i = l r b i )   m o d   1000000007 \sum\limits_{l=1}^n\sum\limits_{r=l}^n(\sum\limits_{i=l}^ra_i)\times(\sum\limits_{i=l}^rb_i) \bmod1000000007 l=1nr=ln(i=lrai)×(i=lrbi)mod1000000007

∣ a i , b i , k ∣ ≤ 1 0 9 , 1 ≤ l ≤ r ≤ n , 1 ≤ n ≤ 5 × 1 0 5 , q ≤ 1 0 6 |a_i,b_i,k|\le 10^9,1\le l \le r \le n,1\le n\le 5\times 10^5,q\le 10^6 ai,bi,k109,1lrn,1n5×105,q106


先推式子。记 S , T S,T S,T 分别是 a , b a,b a,b 的前缀和。
∑ l = 1 n ∑ r = l n ( ∑ i = l r a i ) × ( ∑ i = l r b i ) = ∑ l = 1 n ∑ r = l n ( S r − S l − 1 ) ( T r − T l − 1 ) = ∑ l = 1 n ∑ r = l n ( S r T r + S l − 1 T l − 1 − S r T l − 1 − S l − 1 T r ) = n ∑ i = 1 n S i T i − ∑ l = 1 n ∑ r = l n ( S r T l − 1 + S l − 1 T r ) = ( n + 1 ) ∑ i = 1 n S i T i − ( ∑ i = 1 n S i ) ( ∑ j = 1 n T j ) \begin{aligned} \sum\limits_{l=1}^n\sum\limits_{r=l}^n(\sum\limits_{i=l}^ra_i)\times(\sum\limits_{i=l}^rb_i)&=\sum\limits_{l=1}^n\sum\limits_{r=l}^n(S_r-S_{l-1})(T_r-T_{l-1})\\ &=\sum\limits_{l=1}^n\sum\limits_{r=l}^n(S_rT_r+S_{l-1}T_{l-1}-S_rT_{l-1}-S_{l-1}T_r)\\ &=n\sum\limits_{i=1}^nS_iT_i-\sum\limits_{l=1}^n\sum\limits_{r=l}^n(S_rT_{l-1}+S_{l-1}T_r)\\ &=(n+1)\sum\limits_{i=1}^nS_iT_i-\left(\sum\limits_{i=1}^nS_i\right)\left(\sum\limits_{j=1}^nT_j\right) \\ \end{aligned} l=1nr=ln(i=lrai)×(i=lrbi)=l=1nr=ln(SrSl1)(TrTl1)=l=1nr=ln(SrTr+Sl1Tl1SrTl1Sl1Tr)=ni=1nSiTil=1nr=ln(SrTl1+Sl1Tr)=(n+1)i=1nSiTi(i=1nSi)(j=1nTj)

更具体的推导请参见 P5686 [CSP-S2019 江西] 和积和 。

然后这可以 O ( n ) O(n) O(n) 求。下面考虑修改 b b b 怎么维护。记 A A A 表示 S S S 的后缀和, B B B A A A 的后缀和。

把答案式子写出来:

( n + 1 ) ( ∑ i = 1 l − 1 S i T i + ∑ i = l r S i ( T i + ( i − l + 1 ) k ) + ∑ i = r + 1 n S i ( T i + ( r − l + 1 ) k ) ) − ( ∑ i = 1 n S i ) ( ∑ i = 1 l − 1 T i + ∑ i = l r ( T i + ( i − l + 1 ) k ) + ∑ i = r + 1 n ( T i + ( r − l + 1 ) k ) ) (n+1)\left(\sum\limits_{i=1}^{l-1}S_iT_i+\sum\limits_{i=l}^rS_i(T_i+(i-l+1)k)+\sum\limits_{i=r+1}^nS_i(T_i+(r-l+1)k)\right)-\left(\sum\limits_{i=1}^nS_i\right)\left(\sum\limits_{i=1}^{l-1}T_i+\sum\limits_{i=l}^r(T_i+(i-l+1)k)+\sum\limits_{i=r+1}^n(T_i+(r-l+1)k)\right) (n+1)(i=1l1SiTi+i=lrSi(Ti+(il+1)k)+i=r+1nSi(Ti+(rl+1)k))(i=1nSi)(i=1l1Ti+i=lr(Ti+(il+1)k)+i=r+1n(Ti+(rl+1)k))

化简得到 ( n + 1 ) ( ∑ i = 1 n S i T i + k ( B l − B r + 1 ) ) − ( ∑ i = 1 n S i ) ( ∑ i = 1 n T i + k 2 ( 2 n − r − l + 2 ) ( r − l + 1 ) ) (n+1)\left(\sum\limits_{i=1}^{n}S_iT_i+k\left(B_{l}-B_{r+1}\right)\right)-\left(\sum\limits_{i=1}^nS_i\right)\left(\sum\limits_{i=1}^{n}T_i+\frac k2(2n-r-l+2)(r-l+1)\right) (n+1)(i=1nSiTi+k(BlBr+1))(i=1nSi)(i=1nTi+2k(2nrl+2)(rl+1))

发现都是很好维护的,这道题就解决了。

时间复杂度 O ( n + q ) O(n+q) O(n+q)

#include
using namespace std;
#define ll long long
constexpr ll mod=1e9+7;
const int N=5e5+10;
int n,q;
ll Sum1,Sum2,ans,S[N],T[N],A[N],B[N];
int main()
{
    freopen("meirin.in","r",stdin);
    freopen("meirin.out","w",stdout);
    cin.tie(0)->sync_with_stdio(0);
    cin>>n>>q;
    for(int i=1,x;i<=n;i++) cin>>x,S[i]=(S[i-1]+x+mod)%mod,(Sum1+=S[i])%=mod;
    for(int i=1,x;i<=n;i++) cin>>x,T[i]=(T[i-1]+x+mod)%mod,(Sum2+=T[i])%=mod;
    for(int i=1;i<=n;i++) ans=(ans+S[i]*T[i])%mod;
    for(int i=n;i>=1;i--) A[i]=(A[i+1]+S[i])%mod;
    for(int i=n;i>=1;i--) B[i]=(B[i+1]+A[i])%mod;
    ans=(ans*(n+1)-Sum1*Sum2%mod+mod)%mod;
    for(int i=1,l,r,k;i<=q;i++){
        cin>>l>>r>>k;
        ans=(ans+(B[l]-B[r+1]+mod)*k%mod*(n+1)-1ll*(r-l+1)*(2*n-r-l+2)/2%mod*k%mod*Sum1%mod+mod)%mod;
        cout<<ans<<"\n";
    }
}

你可能感兴趣的:(算法)