zoukankan      html  css  js  c++  java
  • POJ3468

    POJ3468

    博客图片

    题目链接

    POJ3468

    题目概述

    给出一个包含有(N)个元素的数组(a),然后是(m)次操作,操作有以下两种类型:

    1. Q x y((x leq y))计算(sum_{i = x}^y a[i])
    2. C x y d((x leq y))将区间([x,y])内部的每一个(a[i])加上(d).

    对于第一种查询操作输出对应的结果,数据规模:

    [1leq N,Mleq 10^5, -10^9 leq A_i leq 10^9, -10^4leq dleq 10^4. ]

    题目分析

    经典的树状数组区间修改区间查询的题目,利用初始的前缀和数组和用两个树状数组维持区间修改后的(sum_{i=1}^na[i]).

    利用差分转换的原理可以看看这个差分--OIwiki

    通过:

    [sum_{i=1}^{r+1}(r+1-i+1)cdot f_i - sum_{i=1}^{l}(l-i+1)cdot f_i ]

    代码

    /*
     * @Author: Shuo Yang
     * @Date: 2020-08-04 15:46:50
     * @LastEditors: Shuo Yang
     * @LastEditTime: 2020-08-04 16:58:19
     * @FilePath: /Code/POJ/3468.cpp
     */
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int N = 1e6+5;
    ll t1[N];
    ll t2[N];
    ll a[N];
    int n;
    
    inline int lowbit(int x){
        return x & -x;
    }
    
    void add(ll*  t, int k, int x){
        while( k <= n){
            t[k] += x;
            k += lowbit(k);
        }
    }
    
    ll sum(ll* t, int k){
        ll ans = 0;
        while( k > 0){
            ans += t[k];
            k -= lowbit(k);
        }
        return ans;
    }
    
    void addL(int lef, int rig, int x){
        add(t1, lef, x);
        add(t2, lef, lef*x);
        add(t1, rig+1, -x);
        add(t2, rig+1, -(rig+1)*x);
    }
    
    int main(int argc, const char** argv) {
        int m;
        scanf("%d %d",&n,&m);
        for(int i = 1; i <=n ; ++i){
            scanf("%lld", &a[i]);
                a[i] += a[i-1];
        }
        for(int i = 0; i <m; ++i){
            char ch;
            int x,y,c;
            while( ch != 'Q' && ch !='C')
                scanf("%c",&ch);
            // printf("ch=%c**
    ", ch);
            if(ch == 'Q'){
                scanf("%d %d", &x,&y);
                ll ans = (a[y]+(sum(t1,y)*(y+1) - sum(t2,y))) - (a[x-1]+(sum(t1,x)*x-sum(t2,x)));
                printf("%lld
    ", ans);
            }else if( ch == 'C'){
                scanf("%d %d %d",&x,&y,&c);
                addL(x,y,c);
            }
        }
        return 0;
    }
    

    这里面的树状数组t1是维护(sum_{i=1}^{n}(n+1)cdot a[i]),t2数组是维护(sum_{i=1}^{n}icdot a[i]).
    区间更新操作是对这两个操作进行的,至于区间求和在原来前缀和的基础上加上这个区间修改后的差分求和得到的就是最终的结果.
    (纯粹的板子,但是我说不清楚,┭┮﹏┭┮2333333).

    其它

  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/2018slgys/p/13441577.html
Copyright © 2011-2022 走看看