• P2221 [HAOI2012]高速公路(线段树)


    P2221 [HAOI2012]高速公路

    显然答案为 $dfrac{sum_{i=l}^rsum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}$

    下面倒是挺好算,组合数瞎搞

    上面咋算呢

    先考虑每条边被算上的次数$ans = sum_{i=l}^{r}a[i]*(r-i+1)(i-l+1)$

    我们把它拆开再合并瞎搞,按变量$i$的次数分项

    蓝后化出来这个式子:

    $ans = (r - l- r*l+1) *S_{1}+ (l+r)*S_{2}-S_{3}$

    $S_{1} = sum_{i=l}^{r} a[i]$

    $S_{2} = sum_{i=l}^{r} a[i]*i$

    $S_{3} = sum_{i=l}^{r} a[i]*i*i$

    显然这是可以用线段树维护的辣

    区间添加$k$时

    显然$S_{1}+=(r-l+1)*k$

    $S_{2}+=sum i *k$

    $S_{3}+=sum i*i *k$

    再开俩数组维护下$S_{4}=sum i $和$S_{5}=sum i*i$就好辣

    注意我们是按边开线段树,所以$r-=1$,组合数也要改为$C_{r-l+1}^2$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    void read(int &x){
        char c=getchar();x=0; int f=1;
        while(c<'0'||c>'9') f=f&&(c!='-'),c=getchar();
        while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
        x=f?x:-x;
    }
    #define W 400005
    int n,m; ll S1,S2,S3,ans,tot,g;
    ll add[W],s1[W],s2[W],s3[W],s4[W],s5[W];
    #define lc o<<1
    #define rc o<<1|1
    #define mid (l+r)/2
    inline void up(int o){
        s1[o]=s1[lc]+s1[rc],
        s2[o]=s2[lc]+s2[rc],
        s3[o]=s3[lc]+s3[rc];
    }
    void down(int o,int l,int r){
        if(!add[o]) return ;
        s1[lc]+=1ll*(mid-l+1)*add[o], s1[rc]+=1ll*(r-mid)*add[o];
        s2[lc]+=s4[lc]*add[o], s2[rc]+=s4[rc]*add[o];
        s3[lc]+=s5[lc]*add[o], s3[rc]+=s5[rc]*add[o];
        add[lc]+=add[o], add[rc]+=add[o]; add[o]=0;
    }
    void build(int o,int l,int r){
        if(l==r){s4[o]=l,s5[o]=1ll*l*l;    return ;}
        build(lc,l,mid); build(rc,mid+1,r);
        s4[o]=s4[lc]+s4[rc], s5[o]=s5[lc]+s5[rc];
    }
    void Add(int o,int l,int r,int x1,int x2,int v){
        if(x1<=l&&r<=x2){
            add[o]+=v, s1[o]+=(r-l+1)*v,
            s2[o]+=s4[o]*v, s3[o]+=s5[o]*v;
            return ;
        }down(o,l,r);
        if(x1<=mid) Add(lc,l,mid,x1,x2,v);
        if(x2>mid) Add(rc,mid+1,r,x1,x2,v);
        up(o);
    }
    void Ask(int o,int l,int r,int x1,int x2){
        if(x1<=l&&r<=x2){
            S1+=s1[o], S2+=s2[o], S3+=s3[o];
            return ;
        }down(o,l,r);
        if(x1<=mid) Ask(lc,l,mid,x1,x2);
        if(x2>mid) Ask(rc,mid+1,r,x1,x2);
    }
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    int main(){
        char opt[3]; int l,r,v;
        read(n);read(m); --n;
        build(1,1,n);
        while(m--){
            scanf("%s",opt); read(l);read(r); --r;
            if(opt[0]=='C') read(v),Add(1,1,n,l,r,v);
            else{
                S1=S2=S3=0; Ask(1,1,n,l,r);
                ans=1ll*(r-l-1ll*l*r+1)*S1+1ll*(l+r)*S2-S3;
                tot=1ll*(r-l+2)*(r-l+1)/2;
                g=gcd(ans,tot); ans/=g; tot/=g;
                printf("%lld/%lld
    ",ans,tot);
            }
        }return 0;
    }
  • 相关阅读:
    php文件里直接写上<?xml version="1.0" encoding="utf8"?>出错?
    Cannot modify header information headers already sent by错误解决办法
    转:静态类和单例的区别
    转:Spring TransactionDefinition中事务传播的类型
    转:注解+动态代理例子
    转:UML几种类间关系
    转:AOP 的利器:ASM 3.0 介绍
    转:java内部类
    Android 模拟器安装及使用教程
    转:java读取指定package下的class
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10610089.html
Copyright © 2020-2023  润新知