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
",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;
} 
原文地址:https://www.cnblogs.com/hyfer/p/6035547.html