zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers (区间加区间查找)

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    Hint

    The sums may exceed the range of 32-bit integers.
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <map>
    using namespace std;
    
    #define ll long long
    #define eps 1e-9
    
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
    
    ll n, q, x, y, k, ans, a[1000000+8];///开ll,不然数据太大,加起来会爆int
    char c;
    
    struct node
    {
        int l, r;
        ll sum, plz;///开ll,不然数据太大,加起来会爆int
    }tree[4*1000000+8];
    
    void build(int i, ll l, ll r)
    {
        tree[i].l = l;
        tree[i].r = r;
        tree[i].plz = 0;
        if(l == r)///如果已经是叶子结点
            tree[i].sum = a[l];
        else
        {
            ll mid = (l+r)/2;
            build(i*2, l, mid);///往左儿子进行建树
            build(i*2+1, mid+1, r);///往右儿子进行建树
            tree[i].sum = tree[i*2].sum+tree[i*2+1].sum;///父节点的和等于左儿子的和加右儿子的和
        }
    }
    
    void push_down(int i)///把自己的lazytage归零,并给自己的儿子加上,并让自己的儿子加上k*(r-l+1)
    {
        tree[i*2].plz += tree[i].plz;///左儿子的加标记等于父节点的加标记
        tree[i*2+1].plz += tree[i].plz;///右儿子的加标记等于父节点的加标记
        tree[i*2].sum += tree[i].plz*(tree[i*2].r-tree[i*2].l+1);///(左儿子的和)=(左儿子的和)+(左儿子所控制的元素个数)*父节点的加标记
        tree[i*2+1].sum += tree[i].plz*(tree[i*2+1].r-tree[i*2+1].l+1);///(右儿子的和)=(右儿子的和)+(右儿子所控制的元素个数)*父节点的加标记
        tree[i].plz = 0;///父节点标记归零
    }
    
    void pls(int i, ll l, ll r, ll k)///区间加
    {
        if(tree[i].r == r && tree[i].l == l)///如果这个区间恰好是要查找的区间
        {
            tree[i].plz += k;///加标记加上k,表示该区间已经在原来的基础上加了那么多东西
            tree[i].sum += k*(r-l+1);///(这个区间的和)=(这个区间的和)+(要加的数)*(这个区间所控制元素的个数)
            return;
        }
        if(tree[i].l == tree[i].r)///如果为叶子结点,就直接返回他的值
            return;
        push_down(i);///把自己的lazytage归零,并给自己的儿子加上,并让自己的儿子加上k*(r-l+1)
        ll mid = (tree[i].l+tree[i].r)/2;
        if(mid >= r)///如果这个点中间的值大于右边的区间,就往左儿子那边搜索
            pls(i*2, l, r, k);
        else if(mid < l)///如果这个点中间的值小于左边的区间,就往右儿子那边搜索
            pls(i*2+1, l, r, k);
        else///否则就是左儿子右儿子都包含有这个区间,都搜索
        {
            pls(i*2, l, mid, k);
            pls(i*2+1, mid+1, r, k);
        }
        tree[i].sum = tree[i*2].sum + tree[i*2+1].sum;
    }
    
    void search(int i, ll l, ll r)///区间查找
    {
        if(tree[i].l >= l && tree[i].r <= r)///如果这个区间在目标区间内
        {
            ans += tree[i].sum;
            return;
        }
        push_down(i);///把自己的lazytage归零,并给自己的儿子加上,并让自己的儿子加上k*(r-l+1)
        ll mid = (tree[i].l+tree[i].r)/2;
        if(l <= mid)
            search(i*2, l, r);///[l, r]区间不能改,因为题目要搜索的就是[l, r]区间
        if(mid<r)
            search(i*2+1, l, r);
    }
    
    int main()
    {
        scanf("%lld%lld", &n, &q);
        for(int i = 1; i <= n; i++)
            scanf("%lld", &a[i]);
        build(1, 1, n);
        for(int i = 0; i<q; i++)
        {
            ans = 0;
            getchar();
            scanf("%c", &c);
            getchar();
            if(c == 'C')
            {
                scanf("%lld%lld%lld", &x, &y, &k);
                pls(1, x, y, k);
            }
            else
            {
                scanf("%lld%lld", &x, &y);
                search(1, x, y);
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    使用TortoiseSVN建本地仓库20100114
    通用分布式缓存介绍
    fujishu的本真的挺好的
    春晚架构&Ylmf OS&Chrom OS
    sqlserver开发杂记20100120
    tsql使用小记20100127
    mac下hg的安装
    小毛新年祝辞——整装待发,为梦想行
    Memcached客户端评测报告20100125
    小毛iBatis.net保姆系列课程索引
  • 原文地址:https://www.cnblogs.com/RootVount/p/11305036.html
Copyright © 2011-2022 走看看