• luogu P5142 区间方差 十分优美的线段树


    又来了个维护方差的线段树。。。。

    大致推导过程(字丑多包涵QAQ)

    注意取模时要加一些100000007防止出现负数。。

    #include<cstdio>
    #include<iostream>
    #define ll long long
    #define R register long long
    #define ls (tr<<1)
    #define rs (tr<<1|1)
    using namespace std;
    const long long M=1000000007;
    int n,m;
    inline ll g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    ll sum[400010],po[400010];
    void build(int tr,int l,int r) {
        if(l==r) {sum[tr]=g(),po[tr]=sum[tr]*sum[tr]; return;}
        R md=(l+r)>>1;
        build(ls,l,md),build(rs,md+1,r);
        sum[tr]=sum[ls]+sum[rs],po[tr]=po[ls]+po[rs];
    }
    void add(int tr,int l,int r,int pos,ll d) {
        if(l==r) {sum[tr]=d%M; po[tr]=d*d%M; return ;}
        R md=(l+r)>>1;
        if(pos>md) add(rs,md+1,r,pos,d);
        else if(pos<md+1) add(ls,l,md,pos,d);
        sum[tr]=(sum[ls]+sum[rs])%M,po[tr]=(po[ls]+po[rs])%M;
    }
    ll query(int tr,int l,int r,int LL,int RR) {
        if(l==LL&&r==RR) return sum[tr];
        R md=(l+r)>>1;
        if(LL>md) return query(rs,md+1,r,LL,RR);
        else if(RR<md+1) return query(ls,l,md,LL,RR);
        else return (query(ls,l,md,LL,md)+query(rs,md+1,r,md+1,RR))%M;
    }
    ll _query(int tr,int l,int r,int LL,int RR) {
        if(l==LL&&r==RR) return po[tr];
        R md=(l+r)>>1;
        if(LL>md) return _query(rs,md+1,r,LL,RR);
        else if(RR<md+1) return _query(ls,l,md,LL,RR);
        else return (_query(ls,l,md,LL,md)+_query(rs,md+1,r,md+1,RR))%M;
    }
    inline ll qpow(int a) {
        R ret=1,p=M-2; a%=M;
        for(;p;p>>=1,(a*=a)%=M) if(p&1) (ret*=a)%=M;
        return ret;
    }
    inline ll Inv(int x) {
        if(x==1) return 1; if(x<1) return 0;
        return (M-M/x)*Inv(M%x)%M;
    }
    signed main() {
        n=g(),m=g();
        build(1,1,n);
        for(R i=1;i<=m;++i) {
            R k=g(),l=g(),r=g();
            if(k&1) add(1,1,n,l,r);
            else {
                R inv=Inv(r-l+1),ave=query(1,1,n,l,r)*inv%M;
                printf("%lld
    ",((_query(1,1,n,l,r)%M-(ave<<1)*query(1,1,n,l,r)%M+M)*inv%M+ave*ave%M+M)%M);
            }
        }
    }

    也可树状数组,就不多说了(自己没写)(怕是树状数组更易写?)


    2019.04.12

  • 相关阅读:
    综合:bool类型 命名空间 输入输出
    C++命名空间
    C++输入输出
    C++新特性
    C++ IDE环境
    C++简介
    3 python3 编码解码问题 upd接受数据
    2 socket UDP通信
    1 网络基础知识
    15 GIL 全局解释器锁 C语言解决 top ps
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10693561.html
Copyright © 2020-2023  润新知