AC日记——【模板】线段树 1 洛谷 P3372

题目描述

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

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 <cstdio>

#define maxn 100005
#define LL long long

struct TreeNodeType {
    LL l,r,dis,mid,flag;
};
struct TreeNodeType tree[maxn<<2];

LL if_z,n,m,x,ans,type;

char Cget;

inline void in(LL &now)
{
    now=0,if_z=1,Cget=getchar();
    while(Cget>'9'||Cget<'0')
    {
        if(Cget=='-') if_z=-1;
        Cget=getchar();
    }
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
    now*=if_z;
}

void tree_build(LL now,LL l,LL r)
{
    tree[now].l=l,tree[now].r=r;
    if(l==r)
    {
        in(tree[now].dis);
        return ;
    }
    tree[now].mid=(l+r)>>1;
    tree_build(now<<1,l,tree[now].mid);
    tree_build(now<<1|1,tree[now].mid+1,r);
    tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis;
}

void tree_do(LL now,LL l,LL r)
{
    if(tree[now].l==l&&tree[now].r==r)
    {
        if(type==1)
        {
            tree[now].flag+=x;
            tree[now].dis+=(r-l+1)*x;
        }
        else ans+=tree[now].dis;
        return ;
    }
    if(tree[now].flag)
    {
        tree[now<<1].flag+=tree[now].flag;
        tree[now<<1|1].flag+=tree[now].flag;
        tree[now<<1].dis+=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].flag;
        tree[now<<1|1].dis+=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].flag;
        tree[now].flag=0;
    }
    if(l>tree[now].mid) tree_do(now<<1|1,l,r);
    else if(r<=tree[now].mid) tree_do(now<<1,l,r);
    else
    {
        tree_do(now<<1,l,tree[now].mid);
        tree_do(now<<1|1,tree[now].mid+1,r);
    }
    tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis;
}

int main()
{
    in(n),in(m);
    tree_build(1,1,n);
    LL l,r;
    while(m--)
    {
        in(type),in(l),in(r);
        if(type==1) in(x),tree_do(1,l,r);
        else
        {
            ans=0;
            tree_do(1,l,r);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2017-03-14 19:30  IIIIIIIIIU  阅读(212)  评论(0编辑  收藏  举报