【题目描述】:
还记得 NOIP2012 提高组 Day2 中的借教室吗?时光飞逝,光阴荏苒,两年过去了, 曾经借教室的同学们纷纷归还自己当初租借的教室。 请你来解决类似于借教室的另一个问题。
在接受借教室请求的 n 天中,第 i 天剩余的教室为 ai 个。 作为大学借教室服务的负责人,你需要完成如下三种操作共 m 次:
- 第 l 天到第 r 天,每天被归还 d 个教室。
- 询问第 l 天到第 r 天教室个数的平均数。
- 询问第 l 天到第 r 天教室个数的方差。
【输入描述】:
第一行包括两个正整数 n 和 m,其中 n 为借教室的天数,m 为操作次数。接下来一行,共包含 n 个整数,第 i 个整数表示第 i 天剩余教室数目为 ai 个。
接下来 m 行,每行的第一个整数为操作编号(只能为 1 或 2 或 3) ,接下来包含两个正整数 l 和 r,若操作编号为 1,则接下来再包含一个正整数 d。
【输出描述】:
对于每个操作 2 和操作 3,输出一个既约分数(分子与分母互质)表示询问的答案(详见样例)。若答案为 0,请输出“0/1” (不含引号)。
【样例输入】:
5 4
1 2 3 4 5
1 1 2 3
2 2 4
3 2 4
3 1 5
【样例输出】:
4/1
2/3
14/25
【样例说明】:
初始情况下,剩余教室数量为(1, 2, 3, 4, 5)。
第1次操作为第1天到第2天归还3个教室,变为(4, 5, 3, 4, 5)。
第2次操作询问第2天到第4天的平均数为(5+3+4)/3 = 4/1。
第3次操作询问第2天到第4天的方差为(1+1+0)/3 = 2/3。
第4次操作询问第1天到第5天的方差为(0.04+0.64+1.44+0.04+0.64)/5 = 14/25。
【数学贴士】:
n个数的平均数为(x1+…+xn)/n,n个数的方差为((x1-平均数)^2+…+(xn-平均数)^2)/n。
【时间限制、数据范围及描述】:
时间:1s 空间:512M
所有测试点的数据规模如下:
测试点编号:n, m 的规模 约定
测试点1: 1 <= n, m <= 50 不存在操作 3
测试点2: 1 <= n, m <= 100 不存在操作 3
测试点3: 1 <= n, m <= 500
测试点4: 1 <= n, m <= 1,000
测试点5: 1 <= n, m <= 2,500
测试点6: 1 <= n, m <= 5,000
测试点7: 1 <= n, m <= 50,000 不存在操作 3
测试点8: 1 <= n, m <= 60,000 不存在操作 3
测试点9: 1 <= n, m <= 80,000 不存在操作 3
测试点10:1 <= n, m <= 100,000 不存在操作 3
测试点11:1 <= n, m <= 60,000 不存在操作 1
测试点12:1 <= n, m <= 60,000 不存在操作 1
测试点13:1 <= n, m <= 70,000 对于操作1,满足l=r
测试点14:1 <= n, m <= 70,000对于操作1,满足l=r
测试点15:1 <= n, m <= 80,000
测试点16:1 <= n, m <= 80,000
测试点17:1 <= n, m <= 90,000
测试点18:1 <= n, m <= 90,000
测试点19:1 <= n, m <= 100,000
测试点20:1 <= n, m <= 100,000
对于全部测试数据满足:1 <= l <= r <= n,0 <= ai <= 10,1 <= d <= 3, 操作 1 的数量不超过 10%。注意:ai 和 d 的范围很小及操作 1 数量很少的原因是为了保证答案的分子不会很大, 以防止答案的分子溢出 64 位整数的范围, 这与题目做法无关。
线段树维护一个区间和,一个区间平方和,平方和的更新把公式打开即可,求方差也是如此
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <iostream> 9 #include "algorithm" 10 #define lson rt<<1,l,m 11 #define rson rt<<1|1,m+1,r 12 using namespace std; 13 typedef long long LL; 14 const int MAX=100005; 15 int n,m; 16 LL sum[MAX*4],ss[MAX*4],la[MAX*4]; 17 LL s1,s2; 18 LL gcd(LL x,LL y){ 19 if (y==0) return x; 20 return gcd(y,x%y); 21 } 22 void PushUp(int rt){ 23 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 24 ss[rt]=ss[rt<<1]+ss[rt<<1|1]; 25 } 26 void PushDown(int rt,int l,int r){ 27 if (la[rt]){ 28 int m=(l+r)>>1; 29 ss[rt<<1]+=(m-l+1)*la[rt]*la[rt]+2*la[rt]*sum[rt<<1]; 30 ss[rt<<1|1]+=(r-m)*la[rt]*la[rt]+2*la[rt]*sum[rt<<1|1]; 31 sum[rt<<1]+=la[rt]*(m-l+1); 32 sum[rt<<1|1]+=la[rt]*(r-m); 33 la[rt<<1]+=la[rt];la[rt<<1|1]+=la[rt]; 34 la[rt]=0; 35 } 36 } 37 void build(int rt,int l,int r){ 38 la[rt]=0; 39 if (l==r){ 40 scanf("%lld",&sum[rt]); 41 ss[rt]=sum[rt]*sum[rt]; 42 return; 43 } 44 int m=(l+r)>>1; 45 build(lson); 46 build(rson); 47 PushUp(rt); 48 } 49 void add(int rt,int l,int r,int x,int y,LL z){ 50 if (x<=l && r<=y){ 51 la[rt]+=z; 52 ss[rt]+=(r-l+1)*z*z+2*z*sum[rt]; 53 sum[rt]+=z*(r-l+1); 54 return; 55 } 56 int m=(l+r)>>1; 57 PushDown(rt,l,r); 58 if (x<=m) add(lson,x,y,z); 59 if (y>m) add(rson,x,y,z); 60 PushUp(rt); 61 } 62 LL search1(int rt,int l,int r,int x,int y){ 63 if (x<=l && r<=y){ 64 return sum[rt]; 65 } 66 int m=(l+r)>>1; 67 LL an=0; 68 PushDown(rt,l,r); 69 if (x<=m) an+=search1(lson,x,y); 70 if (y>m) an+=search1(rson,x,y); 71 PushUp(rt); 72 return an; 73 } 74 LL search2(int rt,int l,int r,int x,int y){ 75 if (x<=l && r<=y){ 76 return ss[rt]; 77 } 78 int m=(l+r)>>1; 79 LL an=0; 80 PushDown(rt,l,r); 81 if (x<=m) an+=search2(lson,x,y); 82 if (y>m) an+=search2(rson,x,y); 83 PushUp(rt); 84 return an; 85 } 86 int main(){ 87 freopen ("classroom.in","r",stdin); 88 freopen ("classroom.out","w",stdout); 89 int i,j; 90 LL x,y,z,w,s1,s2; 91 scanf("%d%d",&n,&m); 92 build(1,1,n); 93 for (i=1;i<=m;i++){ 94 scanf("%lld",&w); 95 s1=s2=0; 96 if (w==1){ 97 scanf("%lld%lld%lld",&x,&y,&z); 98 add(1,1,n,x,y,z); 99 } 100 if (w==2){ 101 scanf("%lld%lld",&x,&y); 102 s1=search1(1,1,n,x,y); 103 if (s1==0) puts("0/1"); 104 else{ 105 LL zt=gcd(s1,(y-x+1)); 106 printf("%lld/%lld ",s1/zt,(y-x+1)/zt); 107 } 108 } 109 if (w==3){ 110 scanf("%lld%lld",&x,&y); 111 s1=search1(1,1,n,x,y); 112 s2=search2(1,1,n,x,y); 113 LL zt1=s2*(y-x+1)-s1*s1; 114 LL zt=gcd(zt1,(y-x+1)*(y-x+1)); 115 if (zt1==0) puts("0/1"); 116 else printf("%lld/%lld ",zt1/zt,(y-x+1)*(y-x+1)/zt); 117 } 118 } 119 return 0; 120 }