【BZOJ】【2752】【HAOI2012】高速公路(Road)
数学期望/线段树
然而又是一道road= =上一道是2750……
下次不要一看期望题就弃疗么……
期望题≠不可做题……!!
其实在这题中,期望就是(所有情况下 权值之和)/(总方案数)
因为是等概率抽取区间啊= =2333
然而分母很好搞,直接就能算出来,所以我们要来搞分子……
分子其实是个这玩意:$$\sum_{i=l}^{r} v[i]*(i-l+1)*(r-i+1)$$
(我不会告诉你一开始我没加“+1”……)
然而我一开始直接用“几何意义”之类的鬼玩意想往上套,果断跪了Orz
膜拜了zyf的题解,其实正确姿势是这样的!$$\begin{aligned} \sum_{i=l}^{r} v[i]*(i-l+1)*(r-i+1) &= \sum_{i=l}^{r} v[i]*[(r-l-l*r+1)+i*(l+r)-i^2] \\ &=\sum_{i=l}^{r} \big (v[i]*(r-l-l*r+1) + v[i]*i*(l+r)-v[i]*i^2 \big ) \end{aligned}$$
然后知道了这个能干嘛?…………其实………… l 和 r 就是询问的 l 和 r ,所以我们只需要维护与 i 相关的项,即$\sum v[i]$、$\sum v[i]*i$和$\sum v[i]*i^2$就可以计算答案啦~(然而蒟蒻没想到……T^T
嗯……怎么维护?合并就是直接加嘛= =反正只跟坐标相关,然后对整个区间都add一个值?……这是数学问题不要问我>_> (其实我也不会
WA:在upd的时候,由于运算时出现了l*r这个不和谐的项……所以传进去的 l 和 r 得是long long
1 /************************************************************** 2 Problem: 2752 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:3712 ms 7 Memory:16904 kb 8 ****************************************************************/ 9 10 //BZOJ 2752 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline LL getint(){ 23 LL r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=100010; 29 /*******************template********************/ 30 int n,m; 31 struct node{ 32 LL num[4],ad; 33 node(){F(i,0,3) num[i]=0; ad=0;} 34 }t[N<<2]; 35 36 node maintain(node L,node R){ 37 node tmp; 38 F(i,1,3) tmp.num[i]=L.num[i]+R.num[i]; 39 return tmp; 40 } 41 #define mid (l+r>>1) 42 #define L (o<<1) 43 #define R (o<<1|1) 44 void upd(int o,LL l,LL r,LL v){ 45 t[o].ad+=v; 46 t[o].num[1]+=v*(r-l+1); 47 t[o].num[2]+=v*(r+l)*(r-l+1)/2; 48 t[o].num[3]+=v*(r*(r+1)*(2*r+1)-(l-1)*l*(2*l-1))/6;//数学没学好QAQ 49 } 50 void Push_down(int o,int l,int r){ 51 if (t[o].ad){ 52 upd(L,l,mid,t[o].ad); 53 upd(R,mid+1,r,t[o].ad); 54 t[o].ad=0; 55 } 56 } 57 void update(int o,int l,int r,int ql,int qr,LL v){ 58 if (ql<=l && qr>=r) upd(o,l,r,v); 59 else{ 60 Push_down(o,l,r); 61 if (ql<=mid) update(L,l,mid,ql,qr,v); 62 if (qr>mid) update(R,mid+1,r,ql,qr,v); 63 t[o]=maintain(t[L],t[R]); 64 } 65 } 66 node query(int o,int l,int r,int ql,int qr){ 67 if (ql<=l && qr>=r) return t[o]; 68 else{ 69 Push_down(o,l,r); 70 node ans; 71 if (ql<=mid) ans=maintain(ans,query(L,l,mid,ql,qr)); 72 if (qr>mid) ans=maintain(ans,query(R,mid+1,r,ql,qr)); 73 return ans; 74 } 75 } 76 inline LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;} 77 void solve(LL fz,LL fm){ 78 fm=fm*(fm+1)/2; 79 LL d=gcd(abs(fz),fm); 80 // cout << fz <<" "<<fm<<' '<<d<<endl; 81 fz/=d; fm/=d; 82 printf("%lld/%lld\n",fz,fm); 83 } 84 int main(){ 85 #ifndef ONLINE_JUDGE 86 freopen("2752.in","r",stdin); 87 freopen("2752.out","w",stdout); 88 #endif 89 n=getint()-1; m=getint(); 90 char cmd[5]; 91 F(i,1,m){ 92 scanf("%s",cmd); 93 LL l=getint(),r=getint()-1,v; 94 if (cmd[0]=='C'){ 95 v=getint(); 96 update(1,1,n,l,r,v); 97 }else{ 98 node ans=query(1,1,n,l,r); 99 LL fz=ans.num[1]*(r-l-l*r+1)+ans.num[2]*(l+r)-ans.num[3]; 100 solve(fz,r-l+1); 101 } 102 } 103 return 0; 104 }
2752: [HAOI2012]高速公路(road)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 807 Solved: 287
[Submit][Status][Discuss]
Description
Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。
Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。
政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。
无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l<r),在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?
Input
第一行2个正整数N,M,表示有N个收费站,M次调整或询问
接下来M行,每行将出现以下两种形式中的一种
C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v
Q l r 表示对于给定的l,r,要求回答小A的问题
所有C与Q操作中保证1<=l<r<=N
Output
对于每次询问操作回答一行,输出一个既约分数
若答案为整数a,输出a/1
Sample Input
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
Sample Output
8/3
17/6
HINT
数据规模
所有C操作中的v的绝对值不超过10000
在任何时刻任意道路的费用均为不超过10000的非负整数
所有测试点的详细情况如下表所示
Test N M
1 =10 =10
2 =100 =100
3 =1000 =1000
4 =10000 =10000
5 =50000 =50000
6 =60000 =60000
7 =70000 =70000
8 =80000 =80000
9 =90000 =90000
10 =100000 =100000