2017.10.5 高速公路 思考记录

来源:互联网 发布:ai软件工具栏功能 编辑:程序博客网 时间:2024/05/19 10:40

。。一开始死活不知道样例8/3是怎么算出来的、、

后来才发现右端点要-1.。


这个题说是期望,但因为每个点的概率相同,所以直接求和然后除就可以了

维护每个区间的答案,听说直接维护答案很难写,,感觉还可以啊

右端点在右端,左端点在内部的总和、

左端点在左端,右端点在内部的总和,

区间求和

就可以了。



注:

修改一处错误一定要注意连带错误,,特别是复制修改的地方


码:

#include<iostream>#include<cstdio>using namespace std;#define lll long long#define zuo o<<1,l,mid#define you o<<1|1,mid+1,r#define N 100005lll he[N<<2],op,lhe[N<<2],rhe[N<<2],linhe,linrhe,m,n,i,zheng[N<<2],bj[N<<2],linsz,lin[N],xs[N],a,b,c;char ch[99];void up(int o,int l,int r){int ll=o<<1;int rr=o<<1|1;int mid=(l+r)>>1;he[o]=he[ll]+he[rr]+   rhe[ll]*(r-mid)   +   lhe[rr]*(mid-l+1)  ;lhe[o]=lhe[ll]+zheng[ll]*(r-mid)+lhe[rr];rhe[o]=rhe[rr]+zheng[rr]*(mid-l+1)+rhe[ll];zheng[o]=zheng[ll]+zheng[rr];}void down(int o,int l,int r){if(bj[o]!=0){int ll=o<<1;int rr=o<<1|1;int mid=(l+r)>>1;  lhe[ll]+=bj[o]*(1+mid-l+1)*(mid-l+1)/2;  rhe[ll]+=bj[o]*(1+mid-l+1)*(mid-l+1)/2;  he[ll]+=bj[o]*(xs[mid-l+1]);  zheng[ll]+=(mid-l+1)*bj[o];  bj[ll]+=bj[o];  lhe[rr]+=bj[o]*(1+r-mid)*(r-mid)/2;  rhe[rr]+=bj[o]*(1+r-mid)*(r-mid)/2;  he[rr]+=bj[o]*(xs[r-mid]);  zheng[rr]+=(r-mid)*bj[o];  bj[rr]+=bj[o];bj[o]=0;}}void gai(int o,int l,int r){if(a<=l&&r<=b){if(op==0){  lhe[o]+=c*(1+r-l+1)*(r-l+1)/2;  rhe[o]+=c*(1+r-l+1)*(r-l+1)/2;  he[o]+=c*(xs[r-l+1]);  zheng[o]+=(r-l+1)*c;  bj[o]+=c;        }else        {linhe+=he[o]+linrhe*(r-l+1)  +  lhe[o]*(linsz);        linrhe=linrhe+zheng[o]*(linsz)+rhe[o];        linsz+=(r-l+1);        }        return ;}down(o,l,r);int mid=(l+r)>>1;if(a<=mid)gai(zuo);if(b>mid)gai(you);up(o,l,r);}lll gcd(lll a,lll b){if(!b){return a;}return gcd(b,a%b);}int main(){scanf("%lld%lld",&n,&m);n--;    xs[1]=1;lin[1]=1;for(i=2;i<=n;i++){ xs[i]=xs[i-1]+lin[i-1]+i; lin[i]=lin[i-1]+i;}for(i=1;i<=m;i++){scanf("%s",ch);if(ch[0]=='C'){scanf("%lld%lld%lld",&a,&b,&c);op=0;b--;gai(1,1,n);}else{    scanf("%lld%lld",&a,&b);    op=1;    linhe=linrhe=linsz=0;b--;gai(1,1,n);b=b-a+1;lll fm=(1+b)*b/2;lll lca=gcd(linhe,fm);printf("%lld/%lld\n",linhe/lca,fm/lca);}}}