zoukankan      html  css  js  c++  java
  • POJ 3468_A Simple Problem with Integers(线段树)

    题意:

    给定序列及操作,求区间和。

    分析:

    线段树,每个节点维护两个数据:

    • 该区间每个元素所加的值
    • 该区间元素和

    可以分为“路过”该区间和“完全覆盖”该区间考虑。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    //[l,r)
    const int maxn = 300005;
    ll sum[maxn], add[maxn];
    int v[maxn];
    void update(int a, int b, int x, int k, int l, int r)
    {
        if(a <= l && r <= b) add[k] += x;
        else if(l < b && a < r){
            sum[k] += (min(r,b) - max(l,a))*x;
            update(a, b, x, k * 2 + 1, l, (l+r)/2);
            update(a, b,x, k * 2 + 2, (l+r)/2, r);
        }
    }
    ll query(int a, int b, int k, int l, int r)
    {
        if(a >= r|| b <= l) return 0;
        else if(a <= l&&r <= b) return (r - l) * add[k] + sum[k];
        else {
            ll res = (min(b,r)-max(a,l)) * add[k];
            res += query(a, b, k * 2 + 1, l, (l+r)/2);
            res += query(a, b, k * 2 + 2, (l + r)/2, r);
            return res;
        }
    }
    int main (void)
    {
        int n, q;scanf("%d%d",&n,&q);
        int a, b, c;
        for(int i = 0; i < n; i++){
            scanf("%d",&v[i]);
            update(i, i + 1, v[i], 0, 0, n);
        }
        for(int i = 0; i < q; i++){
            getchar();
            if(getchar()=='C'){
                scanf("%d%d%d", &a, &b, &c);
                update(a-1, b, c, 0 , 0, n);
            }else{
                scanf("%d%d",&a, &b);
                printf("%I64d
    ",query(a - 1, b, 0, 0, n));
            }
        }
        return 0;
    }
    

    写的时候还是磕磕绊绊,看来当初学的时候理解的并不好

  • 相关阅读:
    myeclipse 8.6 安装svn插件
    最简单的jdbc程序
    win7 安装Redis
    面试问题
    在linux/unix中查找大文件
    Java:单例模式的七种写法
    JAVA设计模式之单例模式
    java_String和StringBuffer区别分析
    stringbuffer与stringbuilder的区别?
    String与StringBuffer的区别
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758797.html
Copyright © 2011-2022 走看看