1. 程式人生 > >JZOJ 4231. 尋找神格 (Standard IO)

JZOJ 4231. 尋找神格 (Standard IO)

out for n-1 記錄 tput 發生 field fine 一個人

題目

Description

 淬煉完神體,王仙女被傳送到了遙遠處一座沒有神雷的浮島上,發現浮島上除了一扇門以外什麽都沒有。他來到門前,發現上面寫著這樣一段話:
一個神出了擁有強大的神體外,還需要一枚神格。然而,想要獲得神格沒那麽簡單,除了有實力外還需要有運氣。曾經有一個人叫金(jin)字(zi)塔(da),他的神體很強,很壯,可是他根本沒有運氣,所以最後神格拒絕了他。打開這扇門,你將會進入一個神格創造的空間,在那裏,神格將會問你一些問題來測試你解決問題的能力,當然,它的問題將會很難,在你答不出來的時候你可以選擇隨便猜一個答案,以此來展現你的運氣。
王仙女二話不說打開了那扇門,一陣眩暈過後,他來到了一個灰蒙蒙的空間。一個蒼老的聲音在四周響起:小娃娃,我是一枚存在億萬年的神格,我的上一任主人已經死去百萬余年了,我也已經在這裏等待了百萬年了。能否成為我的主人,讓我重現百萬年前的風采,就看你的能力和運氣了。再問問題之前,我要先跟你講一件事。成為一個神後,最大的責任便是保護神界的人民,他們都出生在神界,但並不都具有神的實力。當然,神界人族的內部也有戰爭,他們一共分為N個部落,每兩個部落之間都有可能發生戰爭。為了不然神界人族因為戰爭而損失慘重,神界的諸神將這些部落編號為1~N,當這些部落的人數差距太大時,諸神便會降臨,將一些部落的人帶走,並放一些在別的部落中。而衡量所有部落人數差距的數值便是方差。接下來,我會告訴你一些部落的人數增加或減少的信息,並會不時的詢問你編號為L~R的部落的總人數或是他們部落人數的方差。

Input

第一行包含兩個正整數N,Q,表示部落數和神格的信息數與詢問數總和。
第二行包含N個數,第i個數a_i表示編號為i的部落最初的人數。
接下來Q行,第一個數為t。
當t=0時,這一行還有兩個數a,b,表示編號為a的部落增加了b個人(如果b<0則表示減少了|b|個人)。
當t=1時,這一行還有三個數a,b,c,表示編號為a~b的部落增加了c個人(如果c<0則表示減少了|c|個人)。
當t=2時,這一行還有兩個數a,b,表示神格詢問了編號為a~b的部落現在的總人數。
當t=3時,這一行還有兩個數a,b,表示神格詢問了編號為a~b的部落人數的方差。

Output

對於每個t=2,輸出一行,包含一個整數,表示總人數。
對於每個t=3,輸出一行,包含一個實數,表示方差,結果保留三位小數。

Sample Input

5 5
1 2 3 4 5
0 3 3
1 2 3 6
2 3 5
0 1 2
3 1 5

Sample Output

21
10.640

Data Constraint

對於30%的數據,N≤1000,Q≤1000
對於100%的數據,1≤N≤100000,1≤Q≤100000,|a_i |≤1000,數據保證在任何時候|所有部落總人數|≤〖10〗^9
註:由於神界人族的人數統計是用實際人數減去一個標準值,所以人數可能會出現負數

Hint

方差的定義:
求N個數的方差,設這N個數的平均數為ave,第i個數為x_i
方差=1/n[(x_1-ave)^2+(x_2-ave)^2+?+(x_(n-1)-ave)^2+(x_n-ave)^2]

大意

很難講,慢慢看吧

分析

這道題是一個線段樹 可以單點修改,區間修改,區間查詢

第一二問其實就是建一個數罷了

第三問 也就是查找有線段樹區間是否覆蓋罷了

第四問 才是關鍵:

首先我們要求方差 就要求出總和,然後我們該如何在區間修改其他值呢?

開一個數組add,記錄每一次修改的值,在每一次查找的時候將其他值一起覆蓋

[p]=[p*2]+[p*2+1];

代碼

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll n,m;
ll sum[10000010],num[1000010],add[1000010];
double ans;
void tj(ll p,ll l,ll r,ll a,ll b,ll x)
{
    if (l==a&&r==b){
        sum[p]+=x*x*(r-l+1)+2*num[p]*x;
        num[p]+=x*(r-l+1);
        add[p]+=x;
        return;
    }
    ll mid=(l+r)/2;
    if (add[p]){
        sum[p*2]+=add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];
        num[p*2]+=add[p]*(mid-l+1);
        add[p*2]+=add[p*2]+add[p];
        sum[p*2+1]+=add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];
        num[p*2+1]+=add[p]*(r-mid);
        add[p*2+1]+=add[p];
        add[p]=0;
    }
    if (b<=mid) tj(p*2,l,mid,a,b,x);
    else if (a>mid) tj(p*2+1,mid+1,r,a,b,x);
    else{
        tj(p*2,l,mid,a,mid,x);
        tj(p*2+1,mid+1,r,mid+1,b,x);
    }
    sum[p]=sum[p*2]+sum[p*2+1];
    num[p]=num[p*2]+num[p*2+1];
}
ll h=0;
ll check1(ll p,ll l,ll r,ll a,ll b)
{
    if (l==a&&r==b)
    {
           return num[p];    
    }    
    ll mid=(l+r)/2;
    if (add[p]){
        sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];
        num[p*2]=num[p*2]+add[p]*(mid-l+1);
        add[p*2]=add[p*2]+add[p];
        sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];
        num[p*2+1]=num[p*2+1]+add[p]*(r-mid);
        add[p*2+1]=add[p*2+1]+add[p];
        add[p]=0;
    }
        if (b<=mid) return check1(p*2,l,mid,a,b);
        else if (a>mid) return check1(p*2+1,mid+1,r,a,b);
        else{
            return check1(p*2,l,mid,a,mid)+check1(p*2+1,mid+1,r,mid+1,b);
            }
}
ll hh=0;
ll check2(ll p,ll l,ll r,ll a,ll b)
{
    if (l==a&&r==b)
    {
       return sum[p];
    }    
    ll mid=(l+r)/2;
    if (add[p]){
        sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];
        num[p*2]=num[p*2]+add[p]*(mid-l+1);
        add[p*2]=add[p*2]+add[p];
        sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];
        num[p*2+1]=num[p*2+1]+add[p]*(r-mid);
        add[p*2+1]=add[p*2+1]+add[p];
        add[p]=0;
    }
        if (b<=mid) return check2(p*2,l,mid,a,b);
        else if (a>mid) return check2(p*2+1,mid+1,r,a,b);
        else{
            return check2(p*2,l,mid,a,mid)+check2(p*2+1,mid+1,r,mid+1,b);
            }
}
int main ()
{
    cin>>n>>m;
    ll x;
    for (int i=1;i<=n;i++)
    {
        cin>>x;
        tj(1,1,n,i,i,x);
    }
    ll t,a,b,c;
    double ans;
    for (int i=1;i<=m;i++)
    {
        cin>>t;
        if (t==0)
        {
            cin>>a>>b;
            tj(1,1,n,a,a,b);
        }
        if (t==1)
        {
            cin>>a>>b>>c;
                tj(1,1,n,a,b,c);
        }
        if (t==2)
        {
            cin>>a>>b;
            cout<<check1(1,1,n,a,b)<<endl;
        }
        if (t==3)
        {
            cin>>a>>b;
            ll h=check1(1,1,n,a,b);
            ll hh=check2(1,1,n,a,b);
            double x=h,y=hh,z=(b-a+1);
            ans=(double)y*z;
            ans=(double)(ans-(double)x*x);
            ans=(double)ans/((double)z*z);
            printf("%.10lf\n",ans);
        }
    }
}

JZOJ 4231. 尋找神格 (Standard IO)