zoukankan      html  css  js  c++  java
  • A Simple Problem with Integers(树状数组,改段求段)

                                   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
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXL=100000;
    typedef long long int LL;
    LL b[MAXL+50],c[MAXL+50];
    LL sum[MAXL+50];
    int a[MAXL+50];
    int n,m;
    int lowbit(int k)
    {
        return k&-k;
    }
    void update(LL a[],int i,int value)
    {
        while(i<=n)
        {
            a[i]+=value;
            i+=lowbit(i);
        }
    }
    LL getsum(LL a[],int i)
    {
        LL ans=0;
        while(i>0)
        {
            ans+=a[i];
            i-=lowbit(i);
        }
        return ans;
    }
    int main()
    {
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        memset(sum,0,sizeof(sum));
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            scanf("%d",a+i);
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+a[i];
        int x,y,value;
        char ch;
        int T=m;
        while(T--)
        {
            getchar();
            scanf("%c",&ch);
            if(ch=='C')
            {
                scanf("%d%d%d",&x,&y,&value);
                update(b,x,value);
                update(b,y+1,-value);
                update(c,x,value*x);
                update(c,y+1,-value*(y+1));
            }
            else if(ch=='Q')
            {
                scanf("%d %d",&x,&y);
                LL ans=0;
                ans=sum[y]-sum[x-1];
                ans+=(y+1)*getsum(b,y)-getsum(c,y);
                ans-=(x*getsum(b,x-1))-getsum(c,x-1);
                cout<<ans<<endl;
            }
    
        }
    }
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define N 100005
    using namespace std;
    typedef long long LL;
    LL A[N], B[N], C[N];
    int n, m;
    void addB(int x, int k) //B[i]表示被1...i整体一共加了多少的总和
    {
        for(int i=x; i<=n; i+=i&(-i))
            B[i]+=x*k;
    }
    void addC(int x, int k) //1....x节点的每个节点的增量
    {
        for(int i=x; i>0; i-=i&(-i))
            C[i]+=k;
    }
    LL sumB(int x)
    {
        LL s=0;
        for(int i=x; i>0; i-=i&(-i))
            s+=B[i];
        return s;
    }
    LL sumC(int x) //x节点总共的增量
    {
        LL s=0;
        for(int i=x; i<=n; i+=i&(-i))
            s+=C[i];
        return s;
    }
    LL sum(int x)
    {
        if(x==0)
            return 0;
        else
            return sumC(x)*x + sumB(x-1);
    }
    void update(int a, int b, int c)
    {
        addB(b, c);
        addC(b, c);
        if(a-1>0)
        {
            addB(a-1, -c);
            addC(a-1, -c);
        }
    }
    
    int main()
    {
        int m;
        while(scanf("%d %d", &n,&m)!=EOF)
        {
            for(int i=1; i<=n; ++i)
            {
                scanf("%lld", &A[i]);
                A[i]+=A[i-1];
            }
            int a, b, c;
            char u[2];
            while(m--)
            {
                scanf("%s ",u);
                if(u[0]=='Q')
                {
                    scanf("%d%d", &a, &b);
                    printf("%lld
    ", A[b]-A[a-1]+sum(b)-sum(a-1));  //输出区间a到b的和
    
                }
                else
                {
                     scanf("%d%d%d", &a, &b, &c);
                     update(a, b, c);       //区间a到b加c
                }
            }
        }
        return 0;
    }
    
    
    
    
  • 相关阅读:
    ASP.NET 实现验证码以及刷新验证码
    使用纯生js操作cookie
    TesseractOCR Tutorials
    c# 解析JSON的几种办法
    ElasticSearch常用查询命令-kibana中使用
    ElasticSearch集成IK分词器
    Typora使用教程 之 PicGo集成做图床
    Kibana-CentOS7单机安装测试
    Elasticsearch-CentOS7单机安装测试
    CentOS7安装JDK8
  • 原文地址:https://www.cnblogs.com/jk17211764/p/9677372.html
Copyright © 2011-2022 走看看