[HAOI2012]高速公路(road)

[HAOI2012]高速公路(road)

线段树

bzoj2752

题解:

这里写图片描述

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
typedef long long LL;
const LL N = 200005;

LL s1,s2,s3;
LL n,m;
LL pre1[N],pre2[N],pre3[N];

struct Node{
    LL l,r,mid; LL tag;
    LL sum1,sum2,sum3;
} pool[N*4];

void build(LL x,LL l,LL r){
    Node &t=pool[x];
    t.l=l; t.r=r; t.mid=(l+r)>>1;
    t.sum1=t.sum2=t.sum3=0; t.tag=0;
    if(l!=r){
        build(x*2,t.l,t.mid);
        build(x*2+1,t.mid+1,t.r);
    }
}

void update(LL x){
    Node &t=pool[x];
    t.sum1=t.sum2=t.sum3=0;
    if(t.l!=t.r){
        Node &lch=pool[x*2], &rch=pool[x*2+1];
        t.sum1+=lch.sum1+rch.sum1;
        t.sum2+=lch.sum2+rch.sum2;
        t.sum3+=lch.sum3+rch.sum3;
    }
    if(t.tag){
        t.sum1+=t.tag*(pre1[t.r]-pre1[t.l-1]);
        t.sum2+=t.tag*(pre2[t.r]-pre2[t.l-1]);
        t.sum3+=t.tag*(pre3[t.r]-pre3[t.l-1]);
    }
}

void pushdown(LL x){
    if(pool[x].tag){
        pool[x*2].tag+=pool[x].tag; 
        pool[x*2+1].tag+=pool[x].tag;
        pool[x].tag=0;
        update(x*2); update(x*2+1);
    }
}

void add(LL x,LL ql,LL qr,LL d){
    Node &t=pool[x];
    if(ql<=t.l && t.r<=qr){ 
        t.tag+=d;
    }
    else{
        if(ql<=t.mid) add(x*2,ql,qr,d);
        if(qr>t.mid) add(x*2+1,ql,qr,d);
    }
    update(x);
}

void query(LL x,LL ql,LL qr){
    Node &t=pool[x];
    if(ql<=t.l && t.r<=qr){ s1+=t.sum1; s2+=t.sum2; s3+=t.sum3; }
    else{
        pushdown(x);
        if(ql<=t.mid) query(x*2,ql,qr);
        if(qr>t.mid) query(x*2+1,ql,qr);
    }
}

void init(){
    for(LL i=1;i<=n;i++){
        pre1[i]=pre1[i-1]+1;
        pre2[i]=pre2[i-1]+i;
        pre3[i]=pre3[i-1]+i*i;
    }
}

LL gcd(LL a,LL b){
    return b?gcd(b,a%b):a;
}

int main(){
    freopen("a.in","r",stdin);
    scanf("%lld%lld",&n,&m);
    init();
    build(1,1,n-1);
    char op[5]; LL l,r,d;
    for(LL i=1;i<=m;i++){
        scanf("%s%lld%lld",op,&l,&r); 
        if(op[0]=='C'){
            scanf("%lld",&d);
            add(1,l,r-1,d);
        }
        else{
            s1=s2=s3=0;
            query(1,l,r-1);
//          D(s1); D(s2); D(s3); E;
            LL up = s1*(r-l*r) + s2*(l+r-1) - s3;
            LL down = ((r-l+1)*(r-l))>>1;
//          D(up); D(down); E;
            LL g = gcd(up,down); 
            up/=g; down/=g;
            printf("%lld/%lld\n",up,down);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值