我也就做做水题
易发现公式,分离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; }