线段树(区间更新,区间求和)

我的梦境 提交于 2020-12-13 01:22:41

1082 线段树练习 3

题目描述 Description

给你N个数,有两种操作:


1:给区间[a,b]的所有数增加X


2:询问区间[a,b]的数的和。

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,

 

再接下来一个正整数Q,每行表示操作的个数,

 

如果第一个数是1,后接3个正整数,

 

表示在区间[a,b]内每个数增加X,如果是2,

 

表示操作2询问区间[a,b]的和是多少。

 

pascal选手请不要使用readln读入

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 2 3

样例输出 Sample Output

9

数据范围及提示 Data Size & Hint

数据范围

1<=n<=200000

1<=q<=200000

wa了一发,因为求区间和爆int了

#include <iostream>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include <stdio.h>
#include <string.h>
#define rep(i , n) for(int i = 0 ; i < (n) ; i++)
using namespace std;
const int N = 1100009 ;
long long ans = 0 , flag = 1;
int a[1000009] , b[1000009];

struct Node{
    long long  l , r , val , lazy_tag ;
}tree[N * 4];

void build(int l , int r , int root)
{
    tree[root].l = l , tree[root].r = r ;
    tree[root].lazy_tag = 0 ;
    if(l == r)
    {
        scanf("%d" , &tree[root].val);
        return ;
    }
    int mid = (l + r) >> 1;
    build(l , mid , root*2);
    build(mid+1 , r , root*2+1);
    tree[root].val = tree[root*2].val + tree[root*2+1].val;
}

void pushdown(int root)
{
    tree[root*2].lazy_tag += tree[root].lazy_tag ;//注意标记累计
    tree[root*2+1].lazy_tag += tree[root].lazy_tag ;
    //更新子节点的值
    tree[root*2].val += (tree[root*2].r - tree[root*2].l + 1)*tree[root].lazy_tag ;//子节点的区间长度与父节点的lazy相乘
    tree[root*2+1].val += (tree[root*2+1].r - tree[root*2+1].l + 1)*tree[root].lazy_tag;
    tree[root].lazy_tag = 0 ;//取消父节点的标记
}
void update(int l  , int r ,int addval ,int root )
{
    if(tree[root].l >= l && tree[root].r <= r)
    {
        tree[root].lazy_tag += addval ; // 注意这里标记是累加,之前可以有累计
        tree[root].val += (tree[root].r - tree[root].l + 1) * addval ;//这里用addval相乘,因为每到有标记处都会累计
        return ;
    }
    if(tree[root].lazy_tag)
        pushdown(root);
    int mid = (tree[root].l + tree[root].r) >> 1;
    if(l <= mid)
        update(l , r , addval , root*2);
    if(r > mid)
        update(l , r, addval , root*2+1);

    tree[root].val = tree[root*2].val + tree[root*2+1].val;
}

void  query(int l,int r  ,int root )
{
    if(tree[root].l >= l && tree[root].r <= r)
    {
        ans += tree[root].val ;
        return ;
    }
    if(tree[root].lazy_tag)
        pushdown(root);
    int mid = (tree[root].l + tree[root].r) >> 1;
    if(l <= mid)
        query(l , r , root*2);
    if(r > mid)
        query(l , r , root*2+1);

    tree[root].val = tree[root*2].val + tree[root*2+1].val;
}



int main()
{
    int n ;
    while(~scanf("%d" , &n))
    {
        build(1 , n , 1);
        int q ;
        scanf("%d" , &q);
        for(int i = 0 ; i < q ; i++)
        {
            int f  ;
            scanf("%d" , &f );
            if(f == 1)
            {
                int x , y , addval ;
                scanf("%d%d%d" , &x ,&y , &addval);
                update(x , y , addval , 1);
            }
            else
            {
                int x , y ;
                scanf("%d%d" , &x , &y);
                query(x , y , 1);
                cout << ans << endl ;
                ans = 0 ;
            }
        }
    }

    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!