• 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;
    }
    


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

  • 相关阅读:
    单片机多字节串口接收(转)
    TVS ESD 二极管介绍与应用
    W25X16测试程序
    51单片机基于定时器0的硬件延时代码
    [C#]在Windows Service中使用ThreadPool
    [C#]ASP.NET MVC 3 在线学习资料
    [C#]DataGridView中使用数据绑定Enum类型
    [HIMCM]Consortium可以免费下载了!
    [HIMCM]MathType小练习
    实现在DataGridView的编辑列里面选择列类型ColmnType时,多一种类型CalendarColumn从而增加时间控件
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3138799.html
Copyright © 2020-2023  润新知