[模板]线段树

题目描述

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

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

 

 

正确代码:(错误原因在于pushdown函数,在数据量大的情况下,m-l+1!=len-len/2)

#include<bits/stdc++.h>
using namespace std;
long long int a[1000],val[1700000],lazy[1700000],m,n,op,v,x,y,mul[1700000],mod;
void push_up(long long int root)
{
    val[root]=val[root<<1]+val[root<<1|1];
}
void build(long long int l,long long int r,long long int root)
{
    if(l==r)
    {
        scanf("%lld",&val[root]);
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,root<<1);
    build(mid+1,r,(root<<1)+1);
    push_up(root);
}
void push_down(long long int root,long long int l,long long int r)
{
    int m=(r+l)/2;
    lazy[root<<1]+=lazy[root];
    lazy[(root<<1)+1]+=lazy[root];
    val[root<<1]+=lazy[root]*(m-l+1);
    val[root<<1|1]+=lazy[root]*(r-m);
    lazy[root]=0;
}
void update_line(long long int target_l,long long int target_r,long long int l,long long int r,long long int change,long long int root)
{
    if(target_l>r||target_r<l) return;
    if(target_l<=l&&r<=target_r)
    {
        lazy[root]+=change;
        val[root]+=change*(r-l+1);
        return;
    }
    push_down(root,l,r);
    long long int mid=(l+r)>>1;
    update_line(target_l,target_r,l,mid,change,root<<1);
    update_line(target_l,target_r,mid+1,r,change,root<<1|1);
    push_up(root);
}
long long int query(long long int target_l,long long int target_r,long long int l,long long int r,long long int root)
{
    if(target_l>r||target_r<l) return 0;
    if(target_l<=l&&r<=target_r) return val[root];
    push_down(root,l,r);
    long long int mid=(l+r)>>1;
    return query(target_l,target_r,l,mid,root<<1)+query(target_l,target_r,mid+1,r,root<<1|1);
}

int main()
{
    scanf("%lld%lld",&n,&m);
    build(1,n,1);
    while(m--)
    {
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld%lld%lld",&x,&y,&v);
            update_line(x,y,1,n,v,1);
        }
        else
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",query(x,y,1,n,1));
        }
        
    }
}

 

posted @ 2019-11-28 10:59  satans  阅读(131)  评论(0编辑  收藏  举报