[HAOI2012]高速公路 题解

我也就做做水题

易发现公式,分离i,发现答案只与l、r与v[i]、v[i]*i、v[i]*i*i的区间和有关

用三棵线段树维护即可

#include<iostream>
#include<cstdio>
#define llint long long int 
using namespace std;

const int maxn = 400005;

struct atree1 {
    llint tn, ls[maxn], rs[maxn], sum[maxn], js[maxn], lazy[maxn], fa[maxn];
    void cle() {
        tn=1;
    }
    void build(llint x, llint ll, llint rr, llint f) {
        if(ll == rr) {
            sum[x]=0;
            if(f == 1) js[ll]=js[ll-1]+ll;
            else if(f == 2) js[ll]=js[ll-1]+ll*ll;
            else if(f == 3) js[ll]=ll;
        }
        else {
            llint mid=(ll+rr)/2;
            tn++; ls[x]=tn; fa[tn]=x; build(tn, ll, mid, f);
            tn++; rs[x]=tn; fa[tn]=x; build(tn, mid+1, rr, f);
            sum[x]=sum[ls[x]]+sum[rs[x]];
        }
        return;
    }
    void add(llint l, llint r, llint num, llint x, llint ll, llint rr) {
        if(l > rr || ll > r) return;
        if(l <= ll && rr <= r) lazy[x]+=num; //cout<<' '<<ll<<' '<<rr<<endl, 
        else {
            llint mid=(ll+rr)/2;
            sum[x]+=(js[min(r, rr)]-js[max(l, ll)-1])*num;
            //cout<<' '<<ll<<' '<<rr<<' '<<sum[x]<<endl;
            add(l, r, num, ls[x], ll, mid);
            add(l, r, num, rs[x], mid+1, rr);
        }
        return;
    }
    llint count(llint l, llint r, llint x, llint ll, llint rr) {
        if(l > rr || ll > r) return 0;
        if(l <= ll && rr <= r) return sum[x]+(js[rr]-js[ll-1])*lazy[x];
        else {
            llint mid=(ll+rr)/2;
            sum[x]+=(js[rr]-js[ll-1])*lazy[x];
            lazy[ls[x]]+=lazy[x]; lazy[rs[x]]+=lazy[x]; lazy[x]=0;
            return count(l, r, ls[x], ll, mid) + count(l, r, rs[x], mid+1, rr);
        }
    }
} T1, T2, T3;

llint gcd(llint a, llint b) {
    if(b == 0) return a;
    return gcd(b, a%b);
}

int main() {
    ios::sync_with_stdio(false);
    llint i, n, m, l, r, ta, ans1, ans2;
    char t;
    cin>>n>>m;
    T1.cle(); T2.cle(); T3.cle();
    T1.build(1, 1, n, 1);
    T2.build(1, 1, n, 2);
    T3.build(1, 1, n, 3);
    for(i=1; i <= m; i++) {
        cin>>t;
        if(t == 'C') {
            cin>>l>>r>>ta;
            r--;
            T1.add(l, r, ta, 1, 1, n);
            T2.add(l, r, ta, 1, 1, n);
            T3.add(l, r, ta, 1, 1, n);
        }
        else {
            cin>>l>>r;
            ans1=T1.count(l, r, 1, 1, n)*(r+l-1)-T2.count(l, r, 1, 1, n)-(l*r-r)*T3.count(l, r, 1, 1, n);
            ans2=(r-l+1)*(r-l)/2;
            ta=gcd(ans1, ans2);
            cout<<ans1/ta<<'/'<<ans2/ta<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/crraphael/p/11372504.html