CH模拟赛 还教室
/* 区间操作,可以推一推式子,方差为平方的平均数-平均数的平方,维护区间和与区间平方和,平方和的维护方法类似,式子推一推就行了,注意约分 */ #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #define ll long long #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int N = 100050; ll read(){ ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}; while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}; return x*f; } ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} struct fs{ ll son; ll mo; void yf(){ if(son == 0 || mo == 0){ if(son == 0) mo = 1; return; } ll d = gcd(son,mo); son /= d; mo /= d; } void clear(ll a,ll b){ son = a; mo = b; yf(); } fs operator + (fs b){ fs a=*this; ll d = gcd(a.mo,b.mo); ll lcm = a.mo / d * b.mo; a.son *= lcm / a.mo; b.son *= lcm / b.mo; a.son += b.son; a.mo = lcm; a.yf(); return a; } fs operator - (fs b){ fs a=*this; ll d = gcd(a.mo,b.mo); ll lcm = a.mo / d * b.mo; a.son *= lcm / a.mo; b.son *= lcm / b.mo; a.son -= b.son; a.mo = lcm; if(!a.son) a.mo = 1; else a.yf(); return a; } fs operator * (fs b){ fs a=*this; a.son *= b.son; a.mo *= b.mo; a.yf(); return a; } fs operator / (ll b){ fs a =*this; a.mo *= b; a.yf(); return a; } bool operator < (fs b){ return son*b.mo < mo*b.son; } fs operator - (ll k){ fs b,a=*this; b.clear(k,1); if(a<b) swap(a,b); return a-b; } void print(){ printf("%I64d/%I64d\n",son,mo); } }ans,fd; int n,m;ll val[N]; ll sumv[N<<4],addv[N<<4],powv[N<<4]; ll cmd,op,ql,qr,qv,ans1,ans2; void maintain(int rt){ sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1]; powv[rt] = powv[rt<<1] + powv[rt<<1|1]; } void pushdown(int l,int r,int rt){ int m = (l + r) >> 1; if(!addv[rt]) return; addv[rt<<1] += addv[rt]; addv[rt<<1|1] += addv[rt]; powv[rt<<1] += 2*addv[rt]*sumv[rt<<1] + (m-l+1)*addv[rt]*addv[rt]; powv[rt<<1|1] += 2*addv[rt]*sumv[rt<<1|1] + (r-m)*addv[rt]*addv[rt]; sumv[rt<<1] += addv[rt] * (m-l+1); sumv[rt<<1|1] += addv[rt] * (r-m); addv[rt] = 0; } void build(int l,int r,int rt){ addv[rt] = 0; if(l==r){ powv[rt] = val[l]*val[l]; sumv[rt] = val[l]; return; } int m = (l + r) >> 1; build(lson); build(rson); maintain(rt); } void change(ll l,ll r,int rt){ if(ql <= l && qr >= r){ addv[rt] += qv; powv[rt] += 2*qv*sumv[rt] + qv*qv*(r-l+1); sumv[rt] += qv*(r-l+1); return; } pushdown(l,r,rt); int m = (l + r) >> 1; if(ql <= m) change(lson); if(qr > m) change(rson); maintain(rt); } ll query(int l,int r,int rt){ if(ql <= l && qr >= r){ if(op == 1) return sumv[rt]; else return powv[rt]; } pushdown(l,r,rt); int m = (l + r) >> 1; ll ret = 0; if(ql <= m) ret += query(lson); if(qr > m) ret += query(rson); return ret; } int main(){ freopen("classroom.in","r",stdin); freopen("classroom.out","w",stdout); n =read();m=read(); fo(i,1,n) val[i]=read(); build(1,n,1); fo(i,1,m){ cmd=read();ql=read();qr=read(); if(cmd==1){ qv=read(); change(1,n,1); }else if(cmd == 2){ op = 1; ans1=query(1,n,1); ans2=(qr-ql+1); ans.clear(ans1,ans2); ans.print(); }else if(cmd == 3){ op = 2; ans1=query(1,n,1); ans2=(qr-ql+1); ans.clear(ans1,ans2); ans1=ans2=0; op = 1; ans1=query(1,n,1); ans2=(qr-ql+1); fd.clear(ans1,ans2); fd = fd*fd; ans = ans-fd; ans.print(); } } return 0; }