[模板]线段树

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-05 22:22:40

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数加上x

2.求出某区间每一个数的和

输入格式

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入 #1
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出 #1
11
8
20

说明/提示

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^,保证在int64/long long数据范围内)

 

 

#include<bits/stdc++.h>
using namespace std;
int a[1000],val[1700000],lazy[1700000],m,n,op,v,x,y;
void push_up(int root,int len)
{
    val[root]=val[root<<1]+val[(root<<1)+1]+lazy[root<<1]*(len-len/2)+lazy[root<<1|1]*len/2;
}
void build(int l,int r,int root)
{
    if(l==r)
    {
        scanf("%d",&val[root]);
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,root<<1);
    build(mid+1,r,(root<<1)+1);
    push_up(root,r-l+1);
}
void update(int l,int r,int root,int pos,int change)
{
    if(l==r)
    {
        val[root]+=change;
        return;
    }
    int mid=(r+l)>>1;
    if(pos<mid) update(l,mid,root<<1,pos,change);
    else update(mid+1,r,(root<<1)+1,pos,change);
    push_up(root,r-l+1);
}
void push_down(int root,int len)
{
    if(!lazy[root]) return;
    val[root]+=len*lazy[root];
    lazy[root<<1]+=lazy[root];
    lazy[(root<<1)+1]+=lazy[root];
    lazy[root]=0;
}
void update_line(int target_l,int target_r,int l,int r,int change,int root)
{
    if(target_l<=l&&r<=target_r)
    {
        lazy[root]+=change;
        push_down(root,r-l+1);
        return;
    }
    push_down(root,r-l+1);
    int mid=(l+r)>>1;
    if(target_l<=mid) update_line(target_l,target_r,l,mid,change,root<<1);
    if(target_r>mid) update_line(target_l,target_r,mid+1,r,change,(root<<1)+1);
    push_up(root,r-l+1);
}
int query(int target_l,int target_r,int l,int r,int root)
{
    if(target_l<=l&&r<=target_r) return val[root]+(r-l+1)*lazy[root];
    push_down(root,r-l+1);
    int mid=(l+r)>>1;
    int ans=0;
    if(target_l<=mid) ans+=query(target_l,target_r,l,mid,root<<1);
    if(target_r>mid) ans+=query(target_l,target_r,mid+1,r,(root<<1)+1);
    return ans;
}
int main()
{
    freopen("testdata.in","r",stdin);
    scanf("%d%d",&n,&m);
    build(1,n,1);
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&x,&y,&v);
            update_line(x,y,1,n,v,1);
        }
        else
        {
            scanf("%d%d",&x,&y);
            printf("%d\n",query(x,y,1,n,1));
        }
        
    }
}

 

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