WHYZOJ-#68 还教室(线段树)

【题目描述】:

还记得 NOIP2012 提高组 Day2 中的借教室吗?时光飞逝,光阴荏苒,两年过去了, 曾经借教室的同学们纷纷归还自己当初租借的教室。 请你来解决类似于借教室的另一个问题。

在接受借教室请求的 n 天中,第 i 天剩余的教室为 ai 个。 作为大学借教室服务的负责人,你需要完成如下三种操作共 m 次:

  1. 第 l 天到第 r 天,每天被归还 d 个教室。
  2. 询问第 l 天到第 r 天教室个数的平均数。
  3. 询问第 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 }
未来是什么样,未来会发生什么,谁也不知道。 但是我知道, 起码从今天开始努力, 肯定比从明天开始努力, 要快一天实现梦想。 千里之行,始于足下! ——《那年那兔那些事儿》
原文地址:https://www.cnblogs.com/keximeiruguo/p/7345810.html