poj 3468 A Simple Problem with Integers(线段树区区)

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

题目大意:  给出N个数,和M次查询

                 C a b c  区间[a,b]的值都加上c

                 Q a b     查询区间[a,b]值的和

解题思路:  线段树区间lazy延迟更新,每次插入区间标记lazy

                 下次再操作此区间时用lazy更新下面的子树

                  每个结点存储值是区间的和

                  更新和查询的时间复杂度都是O(logN)

代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAX 201000

#define MID(a,b) (a+b)>>1

#define L(a) a<<1

#define R(a) (a<<1|1)

typedef struct{

    int left,right;

    long long int sum,add;

}Node;



Node Tree[MAX<<2]={0};

long long int num[MAX];



void Build(long long int t,int l,int r)             //以1为根节点建立线段树[l,r]

{

    Tree[t].left=l,Tree[t].right=r;

    if(Tree[t].left==Tree[t].right)

    {

        Tree[t].sum=num[Tree[t].right];

        Tree[t].add=0;

        return ;

    }

    int mid=MID(Tree[t].left,Tree[t].right);

    Build(L(t),l,mid);

    Build(R(t),mid+1,r);

    Tree[t].sum=Tree[L(t)].sum+Tree[R(t)].sum;

}



void Insert(long long int t,int l,int r,long long int m)   //向区间[l,r]插入m

{

    if(Tree[t].left==l&&Tree[t].right==r)

    {

        Tree[t].sum+=(Tree[t].right-Tree[t].left+1)*m;

        Tree[t].add+=m;

        return ;

    }

    if(Tree[t].add!=0)                   //无论是插入还是查询都要更新lazy

    {

        Tree[L(t)].sum+=(Tree[L(t)].right-Tree[L(t)].left+1)*Tree[t].add;

        Tree[R(t)].sum+=(Tree[R(t)].right-Tree[R(t)].left+1)*Tree[t].add;

        Tree[L(t)].add+=Tree[t].add;

        Tree[R(t)].add+=Tree[t].add;

        Tree[t].add=0;

    }

    int mid=MID(Tree[t].left,Tree[t].right);

    if(l>mid)

    {

        Insert(R(t),l,r,m);

    }

    else if(r<=mid)

    {

        Insert(L(t),l,r,m);

    }

    else

    {

        Insert(L(t),l,mid,m);

        Insert(R(t),mid+1,r,m);

    }

    Tree[t].sum=Tree[L(t)].sum+Tree[R(t)].sum;

}



long long int Query(long long int t,int l,int r)     //查询区间[a,b]

{

    if(Tree[t].left==l&&Tree[t].right==r)

    {

        return Tree[t].sum;

    }

    if(Tree[t].add!=0)                 //lazy更新

    {

        Tree[L(t)].sum+=(Tree[L(t)].right-Tree[L(t)].left+1)*Tree[t].add;

        Tree[R(t)].sum+=(Tree[R(t)].right-Tree[R(t)].left+1)*Tree[t].add;

        Tree[L(t)].add+=Tree[t].add;

        Tree[R(t)].add+=Tree[t].add;

        Tree[t].add=0;

    }

    int mid=MID(Tree[t].left,Tree[t].right);

    if(l>mid)

    {

        return Query(R(t),l,r);

    }

    else if(r<=mid)

    {

        return Query(L(t),l,r);

    }

    else

    {

        return Query(L(t),l,mid)+Query(R(t),mid+1,r);

    }

    Tree[t].sum=Tree[L(t)].sum+Tree[R(t)].sum;   //更新结点: 结点的值=左子树+右子树

}



int main()

{

    char ch;

    int n,a,b,c;

    long long int i,m;

    scanf("%d%lld",&n,&m);

    for(i=1;i<=n;i++)         //初始化输入

        scanf("%lld",&num[i]);

    Build(1,1,n);

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

    {

        getchar();

        scanf("%c",&ch);

        if(ch=='C')

        {

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

            Insert(1,a,b,c);            //区间[a,b]都加上c

        }

        else

        {

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

            printf("%lld\n",Query(1,a,b));  //查询区间[a,b]的和

        }

    }

    return 0;

}


注:原创文章,转载请注明出处

 

你可能感兴趣的:(Integer)