Description
Y901高速公路是一條重要的交通紐帶,政府部門建設初期的投入以及使用期間的養護費用都不低,因此政府在這條高速公路上設立了許多收費站。
Y901高速公路是一條由N-1段路以及N個收費站組成的東西向的鏈,我們按照由西向東的順序將收費站依次編號為1~N,從收費站i行駛到i+1(或從i+1行駛到i)需要收取Vi的費用。高速路剛建成時所有的路段都是免費的。
政府部門根據實際情況,會不定期地對連續路段的收費標準進行調整,根據政策漲價或降價。
無聊的小A同學總喜歡研究一些稀奇古怪的問題,他開車在這條高速路上行駛時想到了這樣一個問題:對于給定的l,r(l<r),在第l個到第r個收費站里等概率隨機取出兩個不同的收費站a和b,那么從a行駛到b將期望花費多少費用呢?
Input
第一行2個正整數N,M,表示有N個收費站,M次調整或詢問
接下來M行,每行將出現以下兩種形式中的一種
C l r v 表示將第l個收費站到第r個收費站之間的所有道路的通行費全部增加v
Q l r?? 表示對于給定的l,r,要求回答小A的問題
所有C與Q操作中保證1<=l<r<=N
Output
對于每次詢問操作回答一行,輸出一個既約分數
若答案為整數a,輸出a/1
Sample Input
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
Sample Output
8/3
17/6
HINT
?
數據規模
所有C操作中的v的絕對值不超過10000
在任何時刻任意道路的費用均為不超過10000的非負整數
所有測試點的詳細情況如下表所示
Test N M
1 =10 =10
2 =100 =100
3 =1000 =1000
4 =10000 =10000
5 =50000 =50000
6 =60000 =60000
7 =70000 =70000
8 =80000 =80000
9 =90000 =90000
10 =100000 =100000
?
算期望的話考慮用總權值/總方案。。。
然后如何統計總權值,我們單獨考慮每一條邊會經過多少次來計算貢獻,然后求和。。。
即要求:
然后暴力展開是要求:
那么用線段樹維護i^2*v[i],i*v[i],v[i]的和即可。。。
這個題用cout輸出會RE。。。
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
typedef long long ll;
const int N=600050;
int ls[N*4],rs[N*4],rt,sz,n,m;
char ch[N];
struct data{ll sum1,sum2,sum3;
}tr[N*4];
data operator + (const data &a,const data &b){return (data){a.sum1+b.sum1,a.sum2+b.sum2,a.sum3+b.sum3};
}
ll sum1[N],sum2[N],sum3[N],lazy[N*4];
void pushup(int x){tr[x]=tr[ls[x]]+tr[rs[x]];}
void insert(int &x,int l,int r,int id){if(!x) x=++sz;if(l==r) {tr[x].sum1=tr[x].sum2=tr[x].sum3=0;return;}int mid=(l+r)>>1;if(id<=mid) insert(ls[x],l,mid,id);else insert(rs[x],mid+1,r,id);pushup(x);
}
void Modify(int x,int v,int l,int r){tr[x].sum1+=1ll*v*(sum1[r]-sum1[l-1]);tr[x].sum2+=1ll*v*(sum2[r]-sum2[l-1]);tr[x].sum3+=1ll*v*(sum3[r]-sum3[l-1]);
}
void update(int x,int l,int r,int xl,int xr,int v){if(xl<=l&&r<=xr){Modify(x,v,l,r);lazy[x]+=v;return;}int mid=(l+r)>>1;if(xr<=mid) update(ls[x],l,mid,xl,xr,v);else if(xl>mid) update(rs[x],mid+1,r,xl,xr,v);else update(ls[x],l,mid,xl,mid,v),update(rs[x],mid+1,r,mid+1,xr,v);pushup(x);Modify(x,lazy[x],l,r);
}
data query(int x,int l,int r,int xl,int xr,int la){if(xl<=l&&r<=xr){return (data){tr[x].sum1+la*(sum1[r]-sum1[l-1]),tr[x].sum2+la*(sum2[r]-sum2[l-1]),tr[x].sum3+la*(sum3[r]-sum3[l-1])};}int mid=(l+r)>>1;la+=lazy[x];if(xr<=mid) return query(ls[x],l,mid,xl,xr,la);else if(xl>mid) return query(rs[x],mid+1,r,xl,xr,la);return query(ls[x],l,mid,xl,xr,la)+query(rs[x],mid+1,r,mid+1,xr,la);
}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
main(){scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++) sum1[i]=sum1[i-1]+1,sum2[i]=sum2[i-1]+i,sum3[i]=sum3[i-1]+i*i; for(int i=1;i<=n-1;i++) insert(rt,1,n-1,i);for(int i=1;i<=m;i++){scanf("%s",ch+1);if(ch[1]=='Q'){int l,r;scanf("%lld%lld",&l,&r);r--;data ans=query(rt,1,n-1,l,r,0);ll fm=-ans.sum3+1ll*(l+r)*ans.sum2-1ll*(l-r-1+l*r)*ans.sum1;ll fz=1ll*(r-l+2)*(r-l+1)/2;ll Gcd=gcd(fm,fz);printf("%lld/%lld\n",fm/Gcd,fz/Gcd);}else{int l,r,v;scanf("%lld%lld%lld",&l,&r,&v);r--;update(rt,1,n-1,l,r,v);}}return 0;
}