17年sdnu选拔赛第2场----树状数组+方差公式


Description

An array with length n is given.
       You should support 2 types of operations.

1.x y change the x-th element to y.
       2.l r print the variance of the elements with indices l, l + 1, ... , r.
       As the result may not be an integer, you need print the result after multiplying (r-l+1)^2.

The index of the array is from 1.

Input

The first line is two integer n, m(1 <= n, m <= 2^{16}), indicating the length of the array and the number of operations.    The second line is n integers, indicating the array. The elements of the array 0<=ai <=10^4. The following m lines are the operations. It must be either 1 x y or 2 l r

Output

For each query, print the result.

Sample Input

4 4
1 2 3 4
2 1 4
1 2 4
2 1 4
2 2 4

Sample Output

20
24
2

主要考察方差的使用,方差

维护x和x^2树状数组即可

#include
#include 
#include 
#define ll long long
using namespace std;
ll c[65550];
ll c2[65550];
ll a[65550];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int val)
{
    while(x<=65550)
    {
        c[x]+=val;
        x+=lowbit(x);
    }
}
void add2(int x,ll val)
{
    while(x<=65550)
    {
        c2[x]+=val;
        x+=lowbit(x);
    }
}
ll sum(int x)
{
    ll ans=0;
    while(x>0)
    {
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
ll sum2(int x)
{
    ll ans=0;
    while(x>0)
    {
        ans+=c2[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    int n,m;
    cin>>n>>m;
    memset(c,0,sizeof(c));
    memset(c2,0,sizeof(c2));
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        add(i,a[i]);
        add2(i,a[i]*a[i]);
    }
    while(m--)
    {
        int x;
        scanf("%d",&x);
        if(x==1)
        {
            int u;
            ll v;
            scanf("%d%lld",&u,&v);
            add(u,v-a[u]);
            add2(u,v*v-a[u]*a[u]);
            a[u]=v;
        }
        else
        {
            int l,r;
            scanf("%d%d",&l,&r);
            ll E2=(sum2(r)-sum2(l-1))*(r-l+1);
            ll E=sum(r)-sum(l-1);
            ll D=E2-E*E;
            printf("%lld\n",D);//在这里用cout在玲珑杯上超时,找了好久的原因
        }
    }
    return 0;
}


你可能感兴趣的:(二叉树,树类问题)