线段树加乘维护区间和,区间平方和

在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<int, 3> ar;
int mod = 1e9+7;
const int maxv = 4e6 + 5;
// #define endl "\n"

struct node
{
    int l,r;
    int lazy[2];
    int sum[2];
    #define l(x) tr[x].l 
    #define r(x) tr[x].r 
    #define lazy0(x) tr[x].lazy[0] 
    #define lazy1(x) tr[x].lazy[1] 
    #define sum0(x) tr[x].sum[0] 
    #define sum1(x) tr[x].sum[1] 
}tr[N];

int a[N];

void update(int p)
{
    sum0(p)=sum0(p*2)+sum0(p*2+1);
    sum1(p)=sum1(p*2)+sum1(p*2+1);
}

void init_lazy(int p)
{
    lazy0(p)=1,lazy1(p)=0;
}


void build(int p,int l,int r)
{
    init_lazy(p);
    l(p)=l,r(p)=r;
    if(l==r){
        l(p)=r(p)=l;
        sum0(p)=a[l];
        sum1(p)=a[l]*a[l];
        return ;
    }
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    update(p);
}

void union_lazy(int p,int a,int b)
{
    lazy0(p)*=a;
    lazy1(p)=lazy1(p)*a+b;
}

void cal_lazy(int p,int a,int b)
{
    sum1(p)=a*a*sum1(p)+2*a*b*sum0(p)*(r(p)-l(p)+1)*b*b;
    sum0(p)=a*sum0(p)+(r(p)-l(p)+1)*b;
}

void pushdown(int p)
{
    int a=1,b=0;
    if(lazy0(p)!=1||lazy1(p)!=0){
        a=lazy0(p);
        b=lazy1(p);
        cal_lazy(p*2,a,b),cal_lazy(p*2+1,a,b);
        union_lazy(p*2,a,b),union_lazy(p*2+1,a,b);
        init_lazy(p);
    }
}

void modify(int p,int l,int r,int op,int val)
{
    if(l<=l(p)&&r(p)<=r){
        if(op==0) union_lazy(p,val,0),cal_lazy(p,val,0);
        else union_lazy(p,1,val),cal_lazy(p,1,val);
        return;
    }
    pushdown(p);
    int mid=(l(p)+r(p))/2;
    if(l<=mid) modify(p*2,l,r,op,val);
    if(r>mid) modify(p*2+1,l,r,op,val);
    update(p);
}

ll query(int p,int l,int r,int op)
{
    if(l<=l(p)&&r(p)<=r){
        return tr[p].sum[op];
    }
    pushdown(p);
    ll res=0;
    int mid=(l(p)+r(p))/2;
    if(l<=mid) res+=query(p*2,l,r,op);
    if(r>mid) res+=query(p*2+1,l,r,op);
    return res;
}

void solve()
{
    int n,q;
    cin>>n>>q;
    for(int i=1;i<=n;i++) cin>>a[i];
    build(1,1,n);
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            int l,r;
            cin>>l>>r;
            cout<<query(1,l,r,1)<<endl;
        }
        else if(op==2){
            int l,r;
            cin>>l>>r;
            cout<<query(1,l,r,0)<<endl;
        }
        else if(op==3){
            int l,r,x;
            cin>>l>>r>>x;
            modify(1,l,r,0,x);
        }
        else {
            int l,r,x;
            cin>>l>>r>>x;
            modify(1,l,r,0,x);
        }
    }
} 


int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    t=1;
    // cin>>t;
    while(t--){
        solve();
    }
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值