<线段树>寻找神格
来源:互联网 发布:安卓聊天软件源码 编辑:程序博客网 时间:2024/04/30 04:11
题意
让你维护4种操作:
1.两个数a,b,表示编号为a的部落增加了b个人(如果b<0则表示减少了|b|个人)。
2.三个数a,b,c,表示编号为a~b的部落增加了c个人(如果c<0则表示减少了|c|个人)。
3.两个数a,b,表示神格询问了编号为a~b的部落现在的总人数。
4.两个数a,b,表示神格询问了编号为a~b的部落人数的方差。
方差的定义:
求N个数的方差,设这N个数的平均数为ave,第i个数为x_i
数据范围
对于30%的数据,N≤1000,Q≤1000
对于100%的数据,1≤N≤100000,1≤Q≤100000,|a_i |≤1000,数据保证在任何时候|所有部落总人数|≤〖10〗^9
分析
这题明显的线段树维护,那么前三个操作很好处理,维护总和sum,
这样便可以很好的解决问题了!
补充lazy操作
其实就是一种不到万不得已不更新的一种操作。当更新到k这个点时,先把k更新一次,再在它的标记里面更新(即它的儿子要加多少)。而只有当到了它的儿子时才继续更新,所以这可以大大加速,把很多无用的更新给免去。
var t:array[0..1000000,1..3] of extended; i,n,m,q,j,z,x,y:longint;an,bn,cn,ans,sum,k:extended;a:array[1..100000] of longint;procedure make(k,l,r:longint);var mid:longint;begin mid:=(l+r)shr 1; t[k*2,3]:=t[k*2,3]+t[k,2]*t[k,2]*(mid-l+1)+t[k*2,1]*2*t[k,2]; t[k*2+1,3]:=t[k*2+1,3]+t[k,2]*t[k,2]*(r-mid)+t[k*2+1,1]*2*t[k,2]; t[k*2,1]:=t[k*2,1]+(mid-l+1)*t[k,2]; t[k*2+1,1]:=t[k*2+1,1]+(r-mid)*t[k,2]; t[k*2,2]:=t[k*2,2]+t[k,2]; t[k*2+1,2]:=t[k*2+1,2]+t[k,2]; t[k,2]:=0;end;procedure add(k,l,r,x,y:longint;z:extended);var mid:longint;begin if (l=x)and(r=y) then begin t[k,3]:=t[k,3]+(y-x+1)*z*z+2*t[k,1]*z; t[k,1]:=t[k,1]+z*(y-x+1); t[k,2]:=t[k,2]+z;//lazy 操作 end else begin mid:=(l+r)shr 1; make(k,l,r);//传递标记 if mid<x then add(k*2+1,mid+1,r,x,y,z) else if mid>=y then add(k*2,l,mid,x,y,z) else begin add(k*2,l,mid,x,mid,z); add(k*2+1,mid+1,r,mid+1,y,z); end; t[k,1]:=t[k*2,1]+t[k*2+1,1]; t[k,3]:=t[k*2,3]+t[k*2+1,3]; end;end;procedure find(k,l,r,x,y,z:longint);var mid:longint;begin if (l=x)and(r=y) then begin an:=an+t[k,1];bn:=bn+t[k,3]; end else begin mid:=(l+r)shr 1; make(k,l,r);//传递标记 if mid<x then find(k*2+1,mid+1,r,x,y,z) else if mid>=y then find(k*2,l,mid,x,y,z) else begin find(k*2,l,mid,x,mid,z); find(k*2+1,mid+1,r,mid+1,y,z); end; t[k,1]:=t[k*2,1]+t[k*2+1,1]; t[k,3]:=t[k*2,3]+t[k*2+1,3]; end;end;begin readln(n,m); for i:=1 to n do begin read(x);add(1,1,n,i,i,x);end; for i:=1 to m do begin read(z); case z of 0:begin readln(x,y);add(1,1,n,x,x,y);end; 1:begin readln(x,y,k);add(1,1,n,x,y,k);end; 2:begin bn:=0;an:=0;readln(x,y);find(1,1,n,x,y,0);writeln(an:0:0);end; 3:begin bn:=0;an:=0;readln(x,y); find(1,1,n,x,y,1); cn:=an/(y-x+1); writeln((bn+(y-x+1)*cn*cn-2*cn*an)/(y-x+1):0:4);end; end; end;end.
- <线段树>寻找神格
- 寻找神格
- 【jzoj4845】【寻找】【线段树】
- 食神格
- poj 3264 线段树 寻找最大最小值 SEGMENT TREE
- 线段树寻找部分和为k的第一个位置
- CodeForces 46D 停车场 数据结构+线段树+寻找位置+维护空位+区间赋值
- 线段树小引申(寻找最近的没被标记过的点)
- 不走寻常路:寻找线段的中点
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 树寻找根节点
- 寻找
- 寻找
- 寻找
- 寻找...
- 【Cpp】删除字符串空格
- 安卓控件使用系列20:ProgressBar进度条控件的使用方法
- 弱校联萌十一大决战之强力热身 C题
- Ext.grid.plugin.RowExpander的简单用法
- Spark On YARN内存分配
- <线段树>寻找神格
- 黑马程序员——Java开发前奏
- [经济学原理|政治部分]剩余价值理论
- nyoj 71 独木舟上的旅行
- HDOJ 5480 Conturbatio
- Spark源码系列(七)Spark on yarn具体实现
- [经济学原理|政治部分]资本积累理论
- spark on yarn运行产生缺jar包错误及解决办法
- Json和map相互转换工具类