• 《算法竞赛进阶指南》0x44分块 POJ3468解法二


    题目链接:https://www.acwing.com/problem/content/244/

    树状数组大约比分块快上几倍,分块数据结构也具有很强的利用余地,我们这个问题中,没个分块上有两个属性,一个是sum一个是add,其中一个分块的sum域是真实的,但是其中的a[i]是不真实的,真实的a[i]是a[i]+add[pos[i]]。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn = 100010;
    typedef long long ll;
    int L[maxn],R[maxn];
    ll a[maxn],sum[maxn],add[maxn];
    int pos[maxn];
    int n,m,t;
    void update(int l,int r,int C){
        int p=pos[l],q=pos[r];
        if(p==q){
            for(int i=l;i<=r;i++)a[i]+=C;
            sum[p]+=C*(r-l+1);
            return;
        }else{
            for(int i=p+1;i<=q-1;i++){
                sum[i]+=C*(R[i]-L[i]+1);
                add[i]+=C;
            }
            for(int i=l;i<=R[p];i++)a[i]+=C;
            sum[p]+=C*(R[p]-l+1);
            for(int i=L[q];i<=r;i++)a[i]+=C;
            sum[q]+=C*(r-L[q]+1);
        }
    } 
    ll query(int l,int r){
        ll ans=0;
        int p=pos[l],q=pos[r];
        if(p==q){
            for(int i=l;i<=r;i++)ans+=a[i];
            ans+=add[p]*(r-l+1);
            return ans;
        }else{
            for(int i=p+1;i<=q-1;i++)ans+=sum[i];
            for(int i=l;i<=R[p];i++)ans+=a[i];
            ans+=add[p]*(R[p]-l+1);
            for(int i=L[q];i<=r;i++)ans+=a[i];
            ans+=add[q]*(r-L[q]+1);
            return ans;
        }
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        
        //构建分块 
        t=sqrt(n*1.0);
        for(int i=1;i<=t;i++){
            L[i]=(i-1)*t+1;
            R[i]=i*t;
        }
        if(R[t]<n)++t,L[t]=R[t-1]+1,R[t]=n;
        
        //设置分块上的属性,以及每个位置的归属 
        for(int i=1;i<=t;i++){
            for(int j=L[i];j<=R[i];j++){
                pos[j]=i;
                sum[i]+=a[j];
            }
            add[i]=0;
        }
        
        while(m--){
            char s[10];
            int l,r,d;
            scanf("%s%d%d",s,&l,&r);
            if(s[0]=='C'){
                scanf("%d",&d);
                update(l,r,d);
            }else{
                printf("%lld
    ",query(l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    剖析HBase负载均衡和性能指标
    Hadoop大数据挖掘从入门到进阶实战
    实战Kafka ACL机制
    论文笔记系列--MnasNet:Platform-Aware Neural Architecture Search for Mobile
    在 Vim 中优雅地查找和替换
    VIM的列编辑操作
    理解Pytorch中LSTM的输入输出参数含义
    Python为什么要用抽象类(abc模块)?
    概率密度估计介绍
    Docker永久挂载本地目录
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13304752.html
Copyright © 2020-2023  润新知