zoukankan      html  css  js  c++  java
  • POJ 3468 A Simple Problem with Integers 【树状数组】

    题目链接:http://poj.org/problem?id=3468

    题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b。要求输出v[a]到v[b]之间的和。还有一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c。

    全然是树状数组可以实现的功能,可是假设就这样单纯的套用模板,做另外一种操作是更新每一个值,这种操作就有可能超时。

    换一种思路,既然另外一种操作是给某区间上的全部数加上同样的值,那么应该是可以简化的才对。

    如果数组sum[i]为原数组从v[1]到v[i]的和。数组c1[i]为更新之后,v[i]到v[n]的添加量。分析一下结果ans:

    a,b之间的和ans=sum[b]-sum[a-1]+c1[1]*x + c1[2]*(x-1) + c1[3]*(x-2)+...+c1[x]*1

    ans=sum[b]-sum[a-1]+segema(c1[i]*(x-i+1))

    ans=sum[b]-sum[a-1] + (x+1)*segma(c1[i]) - segma(c1[i]*i)

    令c2[i]=c1[i]*i;

    如此便能利用树状数组解出此题

    代码:

    #include <stdio.h>
    #define N 100001
    #define lowbit(i) ( i & (-i) )
    int n;
    __int64 v[N];
    __int64 c1[N];// 每一个C数组代表v[i-lowbit(i)+1]到v[i]之间的和
    __int64 c2[N];
    __int64 sum[N];
    
    void Updata(__int64 *array,__int64 i,__int64 a)
    {
        for(;i<=n;i+=lowbit(i))
            array[i]+=a;
    }
    __int64 Sumv(__int64 *array,__int64 i)   //求出数组v[1]到v[i]的和
    {
        __int64 result=0;
        while (i>=1)
        {
            result+=array[i];
            i-=lowbit(i);
        }
        return result;
    }
    int main()
    {
        __int64 q,i=0;
        __int64 ans=0;
        scanf("%I64d%I64d",&n,&q);
        for(i=1;i<=n;i++)
            scanf("%I64d",&v[i]);
        for(__int64 i=1;i<=n;i++)
            sum[i]=sum[i-1]+v[i];
        while(q--)
        {
            char ch[2];
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                __int64 s,t;
                scanf("%I64d%I64d",&s,&t);
                ans=sum[t]-sum[s-1];
                ans+=((t+1)*Sumv(c1,t)-Sumv(c2,t));
                ans-=(s*Sumv(c1,s-1)-Sumv(c2,s-1));
                printf("%I64d
    ",ans);
            }
            else
            {
                __int64 a,b,c;
                scanf("%I64d%I64d%I64d",&a,&b,&c);
                Updata(c1,a,c);
                Updata(c1,b+1,-c);
                Updata(c2,a,c*a);
                Updata(c2,b+1,-c*(b+1));
            }
        }
        return 0;
    }
    


  • 相关阅读:
    克如斯卡尔 P1546
    真正的spfa
    第四课 最小生成树 要点
    关于vscode中nullptr未定义
    cmake学习笔记
    python学习笔记
    (BFS 图的遍历) 2906. kotori和迷宫
    (图论基础题) leetcode 997. Find the Town Judge
    (BFS DFS 并查集) leetcode 547. Friend Circles
    (BFS DFS 图的遍历) leetcode 841. Keys and Rooms
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5350267.html
Copyright © 2011-2022 走看看