poj 3468 A Simple Problem with Integers

#include<stdio.h>

struct CNode

{

    int L,R;

    long long nSum;

    long long Inc;

    CNode *pLeft,*pRight;

};

CNode Tree[1000000];

int nCount;

int Mid(CNode *pRoot)

{

    return (pRoot->L+pRoot->R)/2;

}

void BuildTree(CNode *pRoot,int L,int R)

{

    pRoot->L=L;

    pRoot->R=R;

    pRoot->nSum=0;

    pRoot->Inc=0;

    if(L==R)

        return ;

    nCount++;

    pRoot->pLeft=Tree+nCount;

    nCount++;

    pRoot->pRight=Tree+nCount;

    BuildTree(pRoot->pLeft,L,(L+R)/2);

    BuildTree(pRoot->pRight,(L+R)/2+1,R);

}

void Insert(CNode *pRoot,int i,int v)

{

    if(pRoot->L==i&&pRoot->R==i)

    {

        pRoot->nSum=v;

        return ;

    }

    pRoot->nSum+=v;

    if(i<=Mid(pRoot))

        Insert(pRoot->pLeft,i,v);

    else

        Insert(pRoot->pRight,i,v);

}

void Add(CNode *pRoot,int a,int b,long long c)

{

    if(pRoot->L==a&&pRoot->R==b)

    {

        pRoot->Inc+=c;

        return ;

    }

    pRoot->nSum+=c*(b-a+1);

    if(b<=Mid(pRoot))

        Add(pRoot->pLeft,a,b,c);

    else if(a>Mid(pRoot))

        Add(pRoot->pRight,a,b,c);

    else

    {

        Add(pRoot->pLeft,a,Mid(pRoot),c);

        Add(pRoot->pRight,Mid(pRoot)+1,b,c);

    }

}

long long QuerySum(CNode *pRoot,int a,int b)

{

    if(pRoot->L==a&&pRoot->R==b)

    {

        return pRoot->nSum+(pRoot->R-pRoot->L+1)*pRoot->Inc;

    }

    pRoot->nSum+=(pRoot->R-pRoot->L+1)*pRoot->Inc;

    Add(pRoot->pLeft,pRoot->L,Mid(pRoot),pRoot->Inc);

    Add(pRoot->pRight,Mid(pRoot)+1,pRoot->R,pRoot->Inc);

    pRoot->Inc=0;

    if(b<=Mid(pRoot))

        return QuerySum(pRoot->pLeft,a,b);

    else if(a>Mid(pRoot))

        return QuerySum(pRoot->pRight,a,b);

    else

    {

        return QuerySum(pRoot->pLeft,a,Mid(pRoot))+

        QuerySum(pRoot->pRight,Mid(pRoot)+1,b);

    }

}

int main()

{

    int n,q,a,b,c;

    int i,j,k;

    char cmd[10];

    scanf("%d%d",&n,&q);

    nCount=0;

    BuildTree(Tree,1,n);

    for(i=1;i<=n;i++)

    {

        scanf("%d",&a);

        Insert(Tree,i,a);

    }

    for(i=0;i<q;i++)

    {

        scanf("%s",cmd);

        if(cmd[0]=='C')

        {

            scanf("%d%d%d",&a,&b,&c);

            Add(Tree,a,b,c);

        }

        else

        {

            scanf("%d%d",&a,&b);

            printf("%d\n",QuerySum(Tree,a,b));

        }

    }

    return 0;

}

在增加时,如果要加的区间正好覆盖一个
节点,则增加其节点的Inc值,不再往下走
,否则要更新nSum,再将增量往下传
这样更新的复杂度就是O(log(n))
在查询时,如果待查区间不是正好覆盖一
个节点,就将节点的Inc往下带,然后将Inc
代表的所有增量累加到nSum上后将Inc清0
,接下来再往下查询。 Inc往下带的过程也是
区间分解的过程,复杂度也是O(log(n))

你可能感兴趣的:(Integer)