线段树区间修改,区间求和,区间求平方和,最大最小值

o_15.jpg

【代码】

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define f(i,n) for(int i=1;i<=(n);i++)
#define ll long long
#define INF 1<<30
#define N 100010
int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while( isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int a[N];
ll maxn[3*N],sum[3*N],minn[3*N],sumf[3*N],tag[3*N];
int n,q,z;
//向上传递 
void pushup(int o,int l,int r)
{
    int lo=2*o,ro=2*o+1,m=(l+r)>>1;
    sum[o]=sum[lo]+sum[ro];
    maxn[o]=max(maxn[lo],maxn[ro]);
    minn[o]=min(minn[lo],minn[ro]);
    sumf[o]=sumf[lo]+sumf[ro];
}
//定义线段树 
void dingyi(int o,int l,int r)
{
    if(l==r)
    {
        sum[o]=maxn[o]=minn[o]=a[l];
        sumf[o]=a[l]*a[l];
        return;
    }
    int lo=2*o,ro=2*o+1,m=(l+r)>>1;
    dingyi(lo,l,m);
    dingyi(ro,m+1,r);
    pushup(o,l,r);
}
//向下传递tag 
void pushdown(int o,int l,int r)
{
    if(l==r)return;
    int lo=2*o,ro=2*o+1,m=(l+r)>>1;
    if(tag[o])
    {
        tag[lo]+=tag[o];
        tag[ro]+=tag[o];
        sumf[lo]+=(ll)(m-l+1)*tag[o]*tag[o]+(ll)2*tag[o]*sum[lo];
        sumf[ro]+=(ll)(r-m)*tag[o]*tag[o]+(ll)2*tag[o]*sum[ro];
        sum[lo]+=(ll)(m-l+1)*tag[o];
        sum[ro]+=(ll)(r-m)*tag[o];
        maxn[lo]+=tag[o];
        maxn[ro]+=tag[o];
        minn[lo]+=tag[o];
        minn[ro]+=tag[o];
    }
    tag[o]=0;
}
//区间加 
int addl,addr,addi;
void add(int o,int l,int r)
{
    if(l>=addl&&r<=addr)
    {
        sumf[o]+=(ll)(r-l+1)*addi*addi+2ll*addi*sum[o];
        sum[o]+=(ll)(r-l+1)*addi;
        maxn[o]+=addi;
        minn[o]+=addi;
        tag[o]+=addi;
        return;
    }
    pushdown(o,l,r);
    int lo=2*o,ro=2*o+1,m=(l+r)>>1;
    if(addl<=m)add(lo,l,m);
    if(addr>m)add(ro,m+1,r);
    pushup(o,l,r);
}
//区间查询 
ll qsum=0,qsumf=0;
int ql,qr;
void query(int o,int l,int r)
{
    if(l>=ql&&r<=qr)
    {
        qsum+=sum[o];
        qsumf+=sumf[o];
        return;
    }
    int lo=2*o,ro=2*o+1,m=(l+r)>>1;
    pushdown(o,l,r);
    if(ql<=m)query(lo,l,m);
    if(qr>m)query(ro,m+1,r);
    pushup(o,l,r);
}
int main()
{
    n=read();
    q=read();
    f(i,n)a[i]=read();
    dingyi(1,1,n);
    f(i,q)
    {
        z=read();
        if(z==1)
        {
            addl=read();
            addr=read();
            scanf("%lld",&addi);
            if(addi==0)continue;
            add(1,1,n);
        }
        if(z==2)
        {
            ql=read();
            qr=read();
            qsum=0;
            qsumf=0;
            query(1,1,n);
        }
    }
}

转载于:https://www.cnblogs.com/qwerfcxs/p/7811088.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值