30分线段树求调
查看原帖
30分线段树求调
1263684
Elysialr楼主2024/10/16 16:36
#include<bits/stdc++.h>
using namespace std;
#define x_lc (x<<1)
#define x_rc (x<<1|1)
#define x_mid ((t[x].l+t[x].r)>>1)
#define mod 1000000007
#define ll long long

struct SegmentTree{
    ll l,r;
    ll addsum,sqsum;
    ll add;
    ll leng(){
        return r-l+1;
    }
}; 

ll a[100001];
SegmentTree t[400001];

void build(ll x,ll l,ll r){
    t[x].l=l;
    t[x].r=r;
    t[x].add=0;
    if(l==r){
        t[x].sqsum=a[l]*a[l]%mod;
        t[x].addsum=a[l];
        return;
    }
    build(x_lc,l,x_mid);
    build(x_rc,x_mid+1,r);
    t[x].addsum=(t[x_lc].addsum+t[x_rc].addsum)%mod;
    t[x].sqsum=(t[x_lc].sqsum+t[x_rc].sqsum)%mod;
}

void spread(ll x){
    ll y=t[x].add;
    t[x].add=0;
    (t[x_lc].add+=y)%=mod;
    (t[x_rc].add+=y)%=mod;
    (t[x_lc].sqsum+=y*y*t[x_lc].leng()+2*y*t[x_lc].addsum)%=mod;
    (t[x_rc].sqsum+=y*y*t[x_rc].leng()+2*y*t[x_rc].addsum)%=mod;
    (t[x_lc].addsum+=y*t[x_lc].leng())%=mod;
    (t[x_rc].addsum+=y*t[x_rc].leng())%=mod;
}

ll add_sum(ll x,ll l,ll r){
    if(t[x].l>=l&&t[x].r<=r) return t[x].addsum;
    spread(x);
    ll res=0;
    if(x_mid>=l) res+=add_sum(x_lc,l,r);
    if(x_mid+1<=r) res+=add_sum(x_rc,l,r);
    return res%mod;
}

ll squre_sum(ll x,ll l,ll r){
    if(t[x].l>=l&&t[x].r<=r) return t[x].sqsum;
    spread(x);
    ll res=0;
    if(x_mid>=l) res+=squre_sum(x_lc,l,r);
    if(x_mid+1<=r) res+=squre_sum(x_rc,l,r);
    return res%mod;
}

void change(ll x,ll l,ll y){
    if(t[x].l==t[x].r){
        t[x].add+=y;
        (t[x].sqsum+=(t[x].leng()*y%mod+2*t[x].addsum%mod)*y%mod)%=mod;
        (t[x].addsum+=t[x].leng()*y%mod)%=mod;
        return;
    }
    spread(x);
    if(x_mid>=l) change(x_lc,l,y);
    if(x_mid+1<=l) change(x_rc,l,y);
    t[x].sqsum=(t[x_lc].sqsum+t[x_rc].sqsum)%mod;
    t[x].addsum=(t[x_lc].addsum+t[x_rc].addsum)%mod;
}

ll inv(ll a){
    ll res=1;
    for(ll x=a,y=mod-2;y>0;x=(x*x)%mod,y>>=1)
    if(y&1) (res*=x)%=mod;
    return res;
}

ll squ(ll l,ll r){
    ll len=r-l+1;
    ll res=squre_sum(1,l,r)*inv(len)%mod;
    res-=(add_sum(1,l,r)*inv(len)%mod)*(add_sum(1,l,r)*inv(len)%mod)%mod;
    return (res+mod)%mod;
}

int main(){
    ll n,m;
    cin>>n>>m;
    for(ll i=1;i<=n;i++) 
    cin>>a[i];

    build(1,1,n);
    for(ll i=1;i<=m;i++){
        ll k,l,r;
        cin>>k>>l>>r;
        if(k==1) change(1,l,r);
        if(k==2) cout<<squ(l,r)<<endl;
    }
    return 0;
}

AC #1 #5 #10

2024/10/16 16:36
加载中...