noj 1560 Let Slimes Grow Up(线段树,lazy,暂未A)


noj 1560 Let Slimes Grow Up


修改是将一区间的值全加x

查询是查询一区间的方差


利用方差公式D(x)=E(x^2)-E(x)^2

维护区间和和区间平方和,更新的时候要lazy,更新平方和根据完全平方来

运行了两秒半但是WA了,怀疑数据有错,到现在也没人A,先把代码记录下来


#include<stdio.h>
#include<string.h>
#define MAXN 500005
#define ll long long
#define lch p<<1
#define rch p<<1|1
struct node
{
    int l,r;
    ll sum,sum2;
    ll val;
}t[MAXN*4];
void construct(int l,int r,int p)
{
    t[p].l=l,t[p].r=r,t[p].sum=t[p].sum2=t[p].val=0;
    if(l==r)
    {
        scanf("%lld",&t[p].sum);
        t[p].sum2=t[p].sum*t[p].sum;
        return ;
    }
    int m=(l+r)>>1;
    construct(l,m,lch);
    construct(m+1,r,rch);
    t[p].sum=t[lch].sum+t[rch].sum;
    t[p].sum2=t[lch].sum2+t[rch].sum2;
}
void pushdown(int p)
{
    t[lch].val+=t[p].val;
    t[rch].val+=t[p].val;
    
    t[lch].sum2+=2*t[lch].sum*t[p].val+(t[lch].r-t[lch].l+1)*t[p].val*t[p].val;
    t[lch].sum+=t[p].val*(t[lch].r-t[lch].l+1);
    
    t[rch].sum2+=2*t[rch].sum*t[p].val+(t[rch].r-t[rch].l+1)*t[p].val*t[p].val;
    t[rch].sum+=t[p].val*(t[rch].r-t[rch].l+1);
    
    t[p].val=0;
}
void query(int l,int r,int p,ll &ans1,ll &ans2)
{
    if(t[p].l==l&&t[p].r==r)
    {
        ans1+=t[p].sum;
        ans2+=t[p].sum2;
        return ;
    }
    if(t[p].val) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) query(l,r,lch,ans1,ans2);
    else if(l>m) query(l,r,rch,ans1,ans2);
    else query(l,m,lch,ans1,ans2),query(m+1,r,rch,ans1,ans2);
}
void modify(int l,int r,ll val,int p)
{
    if(t[p].l==l&&t[p].r==r)
    {
        t[p].val+=val;
        t[p].sum2+=2*t[p].sum*val+(t[p].r-t[p].l+1)*val*val;
        t[p].sum+=val*(t[p].r-t[p].l+1);
        return ;
    }
    if(t[p].val) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) modify(l,r,val,lch);
    else if(l>m) modify(l,r,val,rch);
    else modify(l,m,val,lch),modify(m+1,r,val,rch);
    
    t[p].sum=t[lch].sum+t[rch].sum;
    t[p].sum2=t[lch].sum2+t[rch].sum2;
}
ll getans(ll x,ll x2,int n)
{
    return (x2*n-x*x)/(n*n);
}
int main()
{
    int n,m;
    int op,l,r;
    ll ans1,ans2,x;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        construct(0,n-1,1);
        while(m--)
        {
            scanf("%d%d%d",&op,&l,&r);
            if(op==1)
            {
                scanf("%lld",&x);
                modify(l,r,x,1);
            }
            else
            {
                ans1=ans2=0;
                query(l,r,1,ans1,ans2);
                //printf("asn1:%d    asn2:%d\n",ans1,ans2);
                printf("%lld\n",getans(ans1,ans2,(r-l+1)));
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值