HAOI2012 高速公路
题目链接 戳我
\(ans=\sum_{i=l}^r a[i]*(i-l+1)*(r-i+1)\)
\(ans=\sum_{i=l}^r a[i]*(-i^2+(r+l)i+(r-l+1-rl))\)
所以说现在我们需要维护的就是五个量——
\(sum1=\sum_{i=l}^r a[i]\)
\(sum2=\sum_{i=l}^r a[i]*i\)
\(sum3=\sum_{i=l}^r a[i]*i^2\)
但是我们进行更改操作的时候可能比较麻烦,所以我们还需要再在建树的时候预处理出来两个值,然后用他们辅助更新。
\(sum4=\sum_{i=l}^r i\)
\(sum5=\sum_{i=l}^r i^2\)
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,m;
long long sum1,sum2,sum3,ans,fn,tmp;
struct Node{long long l,r,tag,sum[6];}t[MAXN<<2];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline long long gcd(long long x,long long y){return y==0?x:gcd(y,x%y);}
inline void build(int x,long long l,long long r)
{
t[x].l=l,t[x].r=r;
if(l==r)
{
t[x].sum[4]=l;
t[x].sum[5]=l*l;
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
t[x].sum[4]=t[ls(x)].sum[4]+t[rs(x)].sum[4];
t[x].sum[5]=t[ls(x)].sum[5]+t[rs(x)].sum[5];
}
inline void push_up(int x)
{
t[x].sum[1]=t[ls(x)].sum[1]+t[rs(x)].sum[1];
t[x].sum[2]=t[ls(x)].sum[2]+t[rs(x)].sum[2];
t[x].sum[3]=t[ls(x)].sum[3]+t[rs(x)].sum[3];
}
inline void modify(int x,int k)
{
t[x].sum[1]+=1ll*(t[x].r-t[x].l+1)*k;
t[x].sum[2]+=1ll*t[x].sum[4]*k;
t[x].sum[3]+=1ll*t[x].sum[5]*k;
t[x].tag+=k;
}
inline void push_down(int x)
{
if(t[x].tag)
{
modify(ls(x),t[x].tag);
modify(rs(x),t[x].tag);
t[x].tag=0;
}
}
inline void update(int x,int ll,int rr,int k)
{
int l=t[x].l,r=t[x].r;
if(ll<=l&&r<=rr)
{
modify(x,k);
return;
}
int mid=(l+r)>>1;
push_down(x);
if(ll<=mid) update(ls(x),ll,rr,k);
if(mid<rr) update(rs(x),ll,rr,k);
push_up(x);
}
inline void query(int x,int ll,int rr)
{
int l=t[x].l,r=t[x].r;
if(ll<=l&&r<=rr)
{
sum1+=t[x].sum[1];
sum2+=t[x].sum[2];
sum3+=t[x].sum[3];
return;
}
int mid=(l+r)>>1;
push_down(x);
if(ll<=mid) query(ls(x),ll,rr);
if(mid<rr) query(rs(x),ll,rr);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
freopen("ce.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++)
{
char op[3];
int x,y,k;
scanf("%s",op);
if(op[0]=='C')
{
scanf("%d%d%d",&x,&y,&k);y--;
update(1,x,y,k);
}
else
{
sum1=sum2=sum3=0;
scanf("%d%d",&x,&y);y--;
query(1,x,y);
ans=1ll*(y-x+1-1ll*y*x)*sum1+(y+x)*sum2-sum3;
fn=1ll*(y-x+2)*(y-x+1)/2;
tmp=gcd(ans,fn);
ans/=tmp,fn/=tmp;
printf("%lld/%lld\n",ans,fn);
}
}
}