• P2221 [HAOI2012]高速公路


    P2221 [HAOI2012]高速公路

    (n-1)条边,查询点((l,r)l<r)相当于边((l,r-1))
    (dis_{i,j})表示边(i)~(j)权之和

    每次查询边((l,r))

    (ans=dfrac{sumlimits_{i=l}^rsumlimits_{j=i}^rdis_{i,j}}{C_{r-l+1}^2}=dfrac{sumlimits_{i=l}^ra_{i}(r-i+1)(i-l+1)}{((r+1)-l)((r+1)-l+1)})

    我们来看上面这部分,拆开后

    (sumlimits_{i=l}^ra_{i}(ri-rl+r-i^2+il-i+i-l+1))

    (sumlimits_{i=l}^ra_{i}(ri-rl+r-i^2+il-l+1))

    (sumlimits_{i=l}^ra_{i}(-i^2+ri+il-rl+r-l+1))

    (sumlimits_{i=l}^ra_{i}((-i^2)+i(l+r)+(r+1-rl-l))

    (sumlimits_{i=l}^ra_{i}(r+1-rl-l)+sumlimits_{i=l}^ra_{i}(i(l+r))+sumlimits_{i=l}^ra_{i}((-i^2))

    线段树维护(sumlimits_{i=l}^ra_{i},sumlimits_{i=l}^ra_{i}*i,sumlimits_{i=l}^ra_{i}*i*i)三个值就行了

    现在考虑区间修改时怎么拆开上面的式子,假设((l,r))加上(val)

    (sum1+=val(r-l+1))

    (sum2+=val[(l+r)(r-l+1)/2])

    维护(sum3)要用到一个常用公式了,不会自行百度(sumlimits_{i=1}^ni^2=dfrac {n(n+1)(2n+1)}{6})

    (sum3+=valdfrac {r(r+1)(2r+1)-(l-1)[(l-1)+1][2(l-1)+1]}{6})

    其他的就是类似模板的东西了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const LL maxn=1e7+1;
    inline LL Read(){
        LL x=0,f=1; char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-') f=-1; c=getchar();
        }
        while(c>='0'&&c<='9')
            x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x*f;
    }
    struct node{
        LL lazy;
        LL sum1,sum2,sum3;
        LL son[2];
    }tree[maxn];
    LL n,m,nod,root;
    inline void Update(LL now){
        LL son0=tree[now].son[0]; LL son1=tree[now].son[1];
        tree[now].sum1=tree[son0].sum1+tree[son1].sum1,
        tree[now].sum2=tree[son0].sum2+tree[son1].sum2,
        tree[now].sum3=tree[son0].sum3+tree[son1].sum3;
    }
    inline void Pushdown(LL now,LL l,LL r){
        if(!tree[now].lazy)
            return;
        LL val=tree[now].lazy;
        if(!tree[now].son[0]) tree[now].son[0]=++nod; LL son0=tree[now].son[0]; 
        if(!tree[now].son[1]) tree[now].son[1]=++nod; LL son1=tree[now].son[1]; 
        LL mid=(l+r)>>1; LL l1=l,r1=mid,l2=mid+1,r2=r;
        tree[son0].lazy+=val,
        tree[son0].sum1+=(r1-l1+1)*val,
        tree[son0].sum2+=(l1+r1)*(r1-l1+1)/2*val,
        tree[son0].sum3+=((r1*(r1+1)*(2*r1+1)-(l1-1)*((l1-1)+1)*(2*(l1-1)+1))/6)*val,
        tree[son1].lazy+=val,
        tree[son1].sum1+=(r2-l2+1)*val,
        tree[son1].sum2+=(l2+r2)*(r2-l2+1)/2*val,
        tree[son1].sum3+=((r2*(r2+1)*(2*r2+1)-(l2-1)*((l2-1)+1)*(2*(l2-1)+1))/6)*val,
        tree[now].lazy=0;
    }
    void Add(LL &now,LL l,LL r,LL lt,LL rt,LL val){
        if(!now)
            now=++nod;
        if(lt<=l&&rt>=r){
            tree[now].lazy+=val,
            tree[now].sum1+=(r-l+1)*val,
            tree[now].sum2+=(l+r)*(r-l+1)/2*val,
            tree[now].sum3+=((r*(r+1)*(2*r+1)-(l-1)*((l-1)+1)*(2*(l-1)+1))/6)*val;
            return;
        }
        Pushdown(now,l,r);
        LL mid=(l+r)>>1;
        if(lt<=mid)
            Add(tree[now].son[0],l,mid,lt,rt,val);
        if(rt>mid)
            Add(tree[now].son[1],mid+1,r,lt,rt,val);
        Update(now);
    }
    LL Query(LL &now,LL l,LL r,LL lt,LL rt){
        if(!now)
            now=++nod;
        if(lt<=l&&rt>=r)
            return (rt-lt+1-lt*rt)*tree[now].sum1+(rt+lt)*tree[now].sum2-tree[now].sum3;
        Pushdown(now,l,r);
        LL mid=(l+r)>>1,sum=0;
        if(lt<=mid)
            sum+=Query(tree[now].son[0],l,mid,lt,rt);
        if(rt>mid)
            sum+=Query(tree[now].son[1],mid+1,r,lt,rt);
        return sum;
    }
    LL Gcd(LL x,LL y){
        if(!y)
            return x;
        return Gcd(y,x%y);
    }
    int main(){
        n=Read()-1,m=Read();
        while(m--){
            char c; scanf(" %c",&c);
            LL l=Read(),r=Read()-1;
            if(c=='C'){
                LL val=Read();
                Add(root,1,n,l,r,val);
            }else{
                LL mu=Query(root,1,n,l,r),zi=((r+1)-l)*((r+1)-l+1)/2;
                LL g=Gcd(mu,zi);
                printf("%lld/%lld
    ",mu/g,zi/g);
            }
        }
        return 0;
    }/*
    */
    
  • 相关阅读:
    AJPFX总结java开发常用类(包装,数字处理集合等)(三)
    AJPFX总结java开发常用类(包装,数字处理集合等)(二)
    AJPFX总结java开发常用类(包装,数字处理集合等)(一)
    AJPFX关于面向对象之封装,继承,多态 (下)
    AJPFX关于面向对象之封装,继承,多态 (上)
    Android IntentFilter匹配规则
    细说Activity与Task(任务栈)
    androidStudio 打包与混淆
    Android activity之间的跳转和数据传递
    android开发中的 Activity 与 Context 区别与联系
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10193345.html
Copyright © 2020-2023  润新知