zoukankan      html  css  js  c++  java
  • [线段树] Jzoj P4231 寻找神格

    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]

    题解

    • 题目大意:给了n个数,要求区间修改,区间求和,区间方差
    • 前两个显然,直接线段树就可以做了,考虑怎么就区间方差
    • 方差=1/n[(x_1-ave)^2+(x_2-ave)^2+⋯+(x_(n-1)-ave)^2+(x_n-ave)^2]
    • =1/n[x_1^2+x_2^2+x_3^2+...+x_n^2+n*ave^2-2*ave*(x_1+x_2+x_3+...+x_n)]
    • 化简到这里可以发现,ave=1/n(x_1+x_2+x_3+...x_n)
    • 那么这样的话,我们只用满足区间和,和区间平方和,这样的话我们就可以得到ans
    • 这题TM的精度是真的恶心!!

    代码

     1 #include <cstdio>
     2 #define ll long long
     3 using namespace std;
     4 struct edge { ll k,l,r; }tree[10000010];
     5 ll n,Q,t,a,b,c,ans1,ans2;
     6 double ans;
     7 void down(ll d,ll l,ll r)
     8 {
     9     ll mid=l+r>>1;
    10      tree[d*2].k+=tree[d].r*tree[d].r*(mid-l+1)+tree[d*2].l*2*tree[d].r,tree[d*2+1].k+=tree[d].r*tree[d].r*(r-mid)+tree[d*2+1].l*2*tree[d].r;
    11     tree[d*2].l+=(mid-l+1)*tree[d].r,tree[d*2+1].l+=(r-mid)*tree[d].r,tree[d*2].r+=tree[d].r,tree[d*2+1].r+=tree[d].r,tree[d].r=0;
    12 }
    13 void insert(ll d,ll l,ll r,ll L,ll R,ll w)
    14 {
    15     if (l==L&&r==R) tree[d].k+=(R-L+1)*w*w+2*tree[d].l*w,tree[d].l+=w*(R-L+1),tree[d].r+=w;
    16     else 
    17     {
    18         ll mid=l+r>>1;down(d,l,r);
    19         if (mid<L) insert(d*2+1,mid+1,r,L,R,w); else if (mid>=R) insert(d*2,l,mid,L,R,w);
    20         else insert(d*2,l,mid,L,mid,w),insert(d*2+1,mid+1,r,mid+1,R,w);
    21         tree[d].k=tree[d*2].k+tree[d*2+1].k,tree[d].l=tree[d*2].l+tree[d*2+1].l;
    22     }
    23 }
    24 void Query(ll d,ll l,ll r,ll L,ll R)
    25 {
    26     if (l==L&&r==R) ans1+=tree[d].l,ans2+=tree[d].k;
    27     else 
    28     {
    29         ll mid=l+r>>1;down(d,l,r);
    30         if (mid<L) Query(d*2+1,mid+1,r,L,R); else if (mid>=R) Query(d*2,l,mid,L,R);
    31         else Query(d*2,l,mid,L,mid),Query(d*2+1,mid+1,r,mid+1,R);
    32         tree[d].l=tree[d*2].l+tree[d*2+1].l,tree[d].k=tree[d*2].k+tree[d*2+1].k;
    33     }
    34 }
    35 int main()
    36 {
    37     scanf("%lld%lld",&n,&Q);
    38     for (ll i=1,x;i<=n;i++) scanf("%lld",&x),insert(1,1,n,i,i,x);
    39     while (Q--)
    40     {
    41         scanf("%lld",&t),ans1=ans2=0;
    42         if (t==0) scanf("%lld%lld",&a,&b),insert(1,1,n,a,a,b);
    43         if (t==1) scanf("%lld%lld%lld",&a,&b,&c),insert(1,1,n,a,b,c);
    44         if (t==2) scanf("%lld%lld",&a,&b),Query(1,1,n,a,b),printf("%lld
    ",ans1);
    45         if (t==3)
    46         {
    47             scanf("%lld%lld",&a,&b);
    48             Query(1,1,n,a,b);
    49             double x=ans1,y=ans2,z=(b-a+1);
    50             ans=(double)((double)y*z-(double)x*x)/((double)z*z);
    51             printf("%.4lf
    ",ans);
    52         }
    53     }
    54 }
  • 相关阅读:
    大型网站架构系列:负载均衡详解(1)
    转:构建高并发高可用的电商平台架构实践
    转:RBAC权限控制
    小型电商网站的架构
    中小型电子商务网站架构
    装饰器在类中的实现
    使用MySQLdb操作Mysql数据库
    unicode转中文以及str形态的unicode转中文
    了解Python内存管理机制,让你的程序飞起来
    多线程初级入门学习
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10296006.html
Copyright © 2011-2022 走看看