bzoj 2752 线段树

来源:互联网 发布:网络女声说唱好听歌曲 编辑:程序博客网 时间:2024/05/15 03:52
题目:Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。
无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l<r),在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?

自己推出来独立做的一道题,很有满足感..=。=
先吐槽一下子:mdzz,明明草稿纸上还是加号,程序里就敲成了减号....
分母(总次数):len*(len+1)/2  (其中 len=r-l+1)
我们把每条边的边权放给它左边那个点,所以我们所有进行更新和询问的区间就变成了[l,r)
对于第i段(左右端点分别是i和i+1),对答案的贡献为  (i-l+1)*(r-i)* v[i] 
所以一段区间[l,r]的答案 = (r+l-1)sigma(v[i]*i)- sigma(v[i]*i*i) + (r-l*r)*sigma(v[i])    (其中,所有的i的范围为[l,r))
我们用线段树,维护三个和即可
type        rec=record           lazy,l,r:int64;           sum:array[0..2] of int64;end;var        m               :longint;        i               :longint;        x,y,t1,t2,tt,z,n:int64;        t               :array[0..400010] of rec;        ch              :char;function gcd(a,b:int64):int64;begin   if b=0 then exit(a) else exit(gcd(b,a mod b));end;procedure build(x:longint;l,r:int64);var        mid:int64;begin   t[x].l:=l; t[x].r:=r;   if l=r then exit;   mid:=(l+r)>>1;   build(2*x,l,mid); build(2*x+1,mid+1,r);end;procedure update(x:longint);var        tt:int64;begin   tt:=t[x].r-t[x].l+1;   t[x].sum[0]:=t[x].sum[0]+t[x].lazy*tt;   t[x].sum[1]:=t[x].sum[1]+t[x].lazy*(t[x].l+t[x].r)*tt div 2;   t[x].sum[2]:=t[x].sum[2]+t[x].lazy*(((t[x].r*(t[x].r+1)*(2*t[x].r+1)) div 6) - (((t[x].l-1)*t[x].l*(2*t[x].l-1)) div 6));   if t[x].l=t[x].r then   begin      t[x].lazy:=0; exit;   end;   inc(t[x*2].lazy,t[x].lazy);   inc(t[2*x+1].lazy,t[x].lazy);   t[x].lazy:=0;end;procedure change(x:longint;l,r,y:int64);var        mid:int64;        len1,len2:int64;begin   if (t[x].l=l) and (t[x].r=r) then   begin      inc(t[x].lazy,y);exit;   end;   if t[x].lazy<>0 then update(x);   mid:=(t[x].l+t[x].r)>>1;   if r<=mid then change(2*x,l,r,y) else     if l>mid then change(2*x+1,l,r,y) else     begin        change(2*x,l,mid,y);        change(2*x+1,mid+1,r,y);     end;   len1:=t[2*x].r-t[2*x].l+1; len2:=t[2*x+1].r-t[2*x+1].l+1;   t[x].sum[0]:=t[2*x].sum[0]+t[2*x+1].sum[0]               +t[2*x].lazy*len1+t[2*x+1].lazy*len2;   t[x].sum[1]:=t[2*x].sum[1]+t[2*x+1].sum[1]               +t[2*x].lazy*(t[x*2].l+t[x*2].r)*len1 div 2               +t[2*x+1].lazy*(t[x*2+1].l+t[x*2+1].r)*len2 div 2;   t[x].sum[2]:=t[2*x].sum[2]+t[2*x+1].sum[2]               +t[2*x].lazy*(((t[x*2].r*(t[x*2].r+1)*(2*t[x*2].r+1)) div 6) - (((t[x*2].l-1)*t[x*2].l*(2*t[x*2].l-1)) div 6))               +t[2*x+1].lazy*(((t[x*2+1].r*(t[x*2+1].r+1)*(2*t[x*2+1].r+1)) div 6) - (((t[x*2+1].l-1)*t[x*2+1].l*(2*t[x*2+1].l-1)) div 6));end;function find(x:longint;l,r:int64;p:longint):int64;var        mid:int64;begin   if t[x].lazy<>0 then update(x);   if (t[x].l=l) and (t[x].r=r) then exit(t[x].sum[p]);   mid:=(t[x].l+t[x].r)>>1;   if r<=mid then exit(find(2*x,l,r,p)) else     if l>mid then exit(find(2*x+1,l,r,p)) else       exit(find(2*x,l,mid,p)+find(2*x+1,mid+1,r,p));end;begin   read(n,m);readln;   build(1,1,n-1);   for i:=1 to m do   begin      read(ch);      if ch='C' then      begin         readln(x,y,z);         change(1,x,y-1,z);      end else      begin         readln(x,y);         t2:=(y-x+1)*(y-x) div 2;         t1:=(y+x-1)*find(1,x,y-1,1)-find(1,x,y-1,2)+(y-x*y)*find(1,x,y-1,0);         if t1<t2 then tt:=gcd(t2,t1) else tt:=gcd(t1,t2);         writeln(t1 div tt,'/',t2 div tt);      end;   end;end.
——by Eirlys


0 0
原创粉丝点击