zoukankan      html  css  js  c++  java
  • 洛谷P5142

    本题化完简单式子然后直接上线段树即可。

    Description

    给定一个序列,对其进行单点修改和求区间方差的操作。

    注意输出方差时要以分数取模形式输出。

    Solution

    单点修改不多说,来看求区间方差。

    假设我们要求的是 ([x,y]) 的方差,也就是求:

    [{frac{1}{y-x+1}sum_{i=x}^y}(a_i-overline a)^2 ]

    化简以下(为了方便设 (d=y-x+1)):

    ({=frac{1}{d}sum_{i=x}^y(a_i^2-2a_ioverline a+overline a^2)})

    ({=frac{1}{d}[sum_{i=x}^y(a_i^2-2a_ioverline a)]+overline a^2})

    ({=frac{1}{d}sum_{i=x}^ya_i^2}-frac{1}{d}sum_{i=x}^ya_icdot 2overline a+overline a^2)

    ({=frac{1}{d}sum_{i=x}^ya_i^2}-2overline a^2+overline a^2)

    ({=frac{1}{d}sum_{i=x}^ya_i^2}-overline a^2)

    所以根据推导过程可以看出,我们需要维护的是区间平方和以及区间和。

    然后就上线段树板子,最后按上面的公式求值,分数换成逆元即可。

    Code

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 510010
    #define INF 0x3f3f3f3f
    #define int long long
    #define Mod 1000000007
    
    using namespace std;
    
    int n,m,a[maxn];
    
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
        return s*w;
    }
    
    int quickpow(int x,int y){
        int ans=1;
        while(y){
            if(y&1)ans=(ans*x)%Mod;
            x=(x*x)%Mod;y>>=1;
        }
        return ans;
    }
    
    namespace Seg{
        #define ls x<<1
        #define rs x<<1|1
        #define f(x) x*x%Mod
        int sum[maxn],fsum[maxn];
        
        void pushup(int x){
            sum[x]=(sum[ls]+sum[rs])%Mod;
            fsum[x]=(fsum[ls]+fsum[rs])%Mod;
        }
        
        void build(int x,int l,int r){
            if(l==r){
                sum[x]=a[l]%Mod;
                fsum[x]=f(a[l]);
                return;
            }
            int mid=l+r>>1;
            build(ls,l,mid);
            build(rs,mid+1,r);
            pushup(x);
        }
        
        void update(int x,int l,int r,int pos,int val){
            if(l==r){
                sum[x]=val%Mod;
                fsum[x]=f(val);
                return;
            }
            int mid=l+r>>1;
            if(pos<=mid) update(ls,l,mid,pos,val);
            else update(rs,mid+1,r,pos,val);
            pushup(x);
        } 
        
        int query(int x,int l,int r,int L,int R){
            int ans=0;
            if(L<=l&&R>=r) return sum[x]%Mod;
            int mid=l+r>>1;
            if(L<=mid) ans=(ans+query(ls,l,mid,L,R))%Mod;
            if(R>=mid+1) ans=(ans+query(rs,mid+1,r,L,R))%Mod;
            return ans%Mod;
        }
        
        int query2(int x,int l,int r,int L,int R){
            int ans=0;
            if(L<=l&&R>=r) return fsum[x]%Mod;
            int mid=l+r>>1;
            if(L<=mid) ans=(ans+query2(ls,l,mid,L,R))%Mod;
            if(R>=mid+1) ans=(ans+query2(rs,mid+1,r,L,R))%Mod;
            return ans%Mod;
        }   
        
        int query3(int x,int l,int r,int L,int R,int val){
            int ans=0;
            if(L<=l&&R>=r) return fsum[x]%Mod;
            int mid=l+r>>1;
            if(L<=mid) ans=(ans+query2(ls,l,mid,L,R))%Mod;
            if(R>=mid+1) ans=(ans+query2(rs,mid+1,r,L,R))%Mod;
            return ans%Mod;
        }
    }
    
    signed main(){
        n=read();m=read();
        for(int i=1;i<=n;i++) 
            a[i]=read();Seg::build(1,1,n);
        for(int i=1,opt,fir,sec;i<=m;i++){
            opt=read();fir=read();sec=read();
            if(opt==1) Seg::update(1,1,n,fir,sec);
            else{
                int ni=quickpow(sec-fir+1,Mod-2);
                int ave=Seg::query(1,1,n,fir,sec)*ni%Mod;
                int ans=Seg::query2(1,1,n,fir,sec)*ni%Mod-f(ave);
                printf("%lld
    ",(ans%Mod+Mod)%Mod);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    DIV+CSS一种简单的左边图片右边多行文字的布局
    超级精简的鼠标触发式下拉菜单
    JQuery全选反选 随其他checkbox自动勾选全选反选
    asp.net后台注册JavaScript
    IE浏览器中iframe背景BODY透明
    iframe自适应高度的超精简方法 IE6/7/8/9 &amp; FF经测试完全通过
    Button1.Attributes.Add() 方法小结
    在美女秘书的身体上寻找股市的趋势!很准的!
    无意中发现google Reader中的内容居然不与RSS源同步!
    参加阿里软件“旺斯卡”,居然给我寄来了1件T恤和1个4GB优盘
  • 原文地址:https://www.cnblogs.com/KnightL/p/14700879.html
Copyright © 2011-2022 走看看