考虑每条路做的贡献,比左端点小的端点数*比右端点大的端点数
推一下柿子就发现要在线段树上分别维护 vi, i*vi, i*i*vi的区间和,好久没写了QAQ
考虑区间加操作对区间和的影响,在pushdown,update里加上影响
#include<bits/stdc++.h>
#define lll long long
#define l o<<1
#define r o<<1|1
using namespace std;
lll sum1[500005],sum2[500005],sum3[500005];//vi i*vi i*i*vi的线段树
lll lz[500005];
lll cal(lll L,lll R){//i*i的(l,r)部分和
L--;
return R*(R+1)*(2*R+1)/6-L*(L+1)*(2*L+1)/6;
}
void pushup(lll o){
sum1[o]=sum1[l]+sum1[r];
sum2[o]=sum2[l]+sum2[r];
sum3[o]=sum3[l]+sum3[r];
}
void pushdown(lll L,lll R,lll o){
if(lz[o]!=0){
lll m=(L+R)>>1;
lz[l]+=lz[o];lz[r]+=lz[o];
sum1[l]+=(m-L+1)*lz[o];
sum1[r]+=(R-m)*lz[o];
sum2[l]+=lz[o]*(L+m)*(m-L+1)/2;//这里不是lz[l]!!! ,lz[l]是给o的左儿子l的左右儿子加的
sum2[r]+=lz[o]*(m+1+R)*(R-m)/2;
sum3[l]+=lz[o]*cal(L,m);
sum3[r]+=lz[o]*cal(m+1,R);
lz[o]=0;
}
}
lll query1(lll ql,lll qr,lll L,lll R,lll o,lll ty){//鏌ヨsum1
if(ql<=L&&qr>=R){//褰撳墠鏄瓙鍖洪棿
if(ty==1)return sum1[o];
if(ty==2)return sum2[o];
if(ty==3)return sum3[o];
}
lll m=(L+R)>>1;lll ans=0;
pushdown(L,R,o);
if(ql<=m)ans+=query1(ql,qr,L ,m,l,ty);
if(qr>m) ans+=query1(ql,qr,m+1,R,r,ty);
return ans;
}
void update(lll ql,lll qr,lll L,lll R,lll o,lll val){
if(ql<=L&&qr>=R){
lz[o]+=val;
sum1[o]+=(R-L+1)*val;
sum2[o]+=(L+R)*(R-L+1)/2*val;
sum3[o]+=cal(L,R)*val;
return;
}
lll m=(L+R)>>1;
pushdown(L,R,o);
if(ql<=m)update(ql,qr,L ,m,l,val);
if(qr>m) update(ql,qr,m+1,R,r,val);
pushup(o);
}
int main(){
//ios::sync_with_stdio(false);
int n,q;scanf("%d %d",&n,&q);
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
memset(sum3,0,sizeof(sum3));
memset(lz,0,sizeof(lz));
while(q--){
char c[2];
scanf("%s",&c);
if(c[0]=='C'){
lll ll,rr,vv;scanf("%lld %lld %lld",&ll,&rr,&vv);rr--;
update(ll,rr,1,n,1,vv);
}else{
lll ll,rr;scanf("%lld %lld",&ll,&rr);rr--;
lll ans1=query1(ll,rr,1,n,1,1)*(rr-ll+1-rr*ll)+
query1(ll,rr,1,n,1,2)*(rr+ll)+
query1(ll,rr,1,n,1,3)*(-1);
lll ans2=(rr-ll+2)*(rr-ll+1)/2;
lll gcd=__gcd(ans1,ans2);
printf("%lld/%lld\n",ans1/gcd,ans2/gcd);
}
}
system("pause");
}