还教室 CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
【引子】
还记得 NOIP 2012 提高组 Day2 中的借教室吗?时光飞逝,光阴荏苒,两年
过去了,曾经借教室的同学们纷纷归还自己当初租借的教室。请你来解决类似于
借教室的另一个问题。
【问题描述】
在接受借教室请求的 n 天中,第 i 天剩余的教室为 a i 个。作为大学借教室服
务的负责人,你需要完成如下三种操作共 m 次:
① 第 l 天到第 r 天,每天被归还 d 个教室。
② 询问第 l 天到第 r 天教室个数的平均数。
③ 询问第 l 天到第 r 天教室个数的方差。
【输入格式】
第一行包括两个正整数 n 和 m,其中 n 为借教室的天数,m 为操作次数。
接下来一行, 共包含 n 个整数, 第 i 个整数表示第 i 天剩余教室数目为 a i 个。
接下来 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
推导一下方差
D(X)=E(X^2)-E^2(X)
线段树维护区间和和区间平方和
区间平方和 t[o].s2+=d*d*(r-l+1)+2*d*t[o].s
PS:r-l+1的平方爆int了
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> using namespace std; const int N=1e5+5; #define m (l+r)/2 #define lson o<<1,l,m #define rson o<<1|1,m+1,r #define lc o<<1 #define rc o<<1|1 typedef long long ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,q,flag,l,r; ll d; struct node{ ll s,s2,lazy; }t[N<<2]; inline void paint(int o,int l,int r,ll d){ t[o].lazy+=d; t[o].s2+=d*d*(r-l+1)+2*d*t[o].s; t[o].s+=d*(r-l+1); } inline void merge(int o){ t[o].s=t[lc].s+t[rc].s; t[o].s2=t[lc].s2+t[rc].s2; } inline void pushDown(int o,int l,int r){ if(t[o].lazy){ ll d=t[o].lazy; paint(lson,d); paint(rson,d); t[o].lazy=0; } } void build(int o,int l,int r){ if(l==r) {ll a=read();t[o].s=a;t[o].s2=a*a;} else{ build(lson); build(rson); merge(o); } } void add(int o,int l,int r,int ql,int qr,ll d){ if(ql<=l&&r<=qr) paint(o,l,r,d); else{ pushDown(o,l,r); if(ql<=m) add(lson,ql,qr,d); if(m<qr) add(rson,ql,qr,d); merge(o); } } ll query1(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return t[o].s; else{ pushDown(o,l,r); ll ans=0; if(ql<=m) ans+=query1(lson,ql,qr); if(m<qr) ans+=query1(rson,ql,qr); return ans; } } ll query2(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return t[o].s2; else{ pushDown(o,l,r); ll ans=0; if(ql<=m) ans+=query2(lson,ql,qr); if(m<qr) ans+=query2(rson,ql,qr); return ans; } } inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} void print(ll x,ll y){ ll g=gcd(x,y); printf("%lld/%lld ",x/g,y/g); } int main(){ n=read();q=read(); build(1,1,n); for(int i=1;i<=q;i++){ flag=read();l=read();r=read(); if(flag==1){d=read();add(1,1,n,l,r,d);} else if(flag==2){ ll x=query1(1,1,n,l,r),len=r-l+1; print(x,len); }else{ ll x1=query1(1,1,n,l,r),x2=query2(1,1,n,l,r),len=r-l+1;//printf("hi %lld %lld ",x1,x2); print(len*x2-x1*x1,len*len); } } }