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);
        }
    }
}
posted @ 2019-03-04 10:20  风浔凌  阅读(160)  评论(0编辑  收藏  举报