洛谷P3372 【模板】线段树 1

xiaoxiao2021-02-28  112

最近才学的线段树,做一道练练手。。。

题目描述

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

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<iostream> #include<cstdlib> #include<cstring> #include<cstdio> struct node {     int l,r;     long long sum,add; }    tr[400005]; inline void build(int rt,int l,int r) {     tr[rt].l=l,tr[rt].r=r;     if(l==r)     {         long long x;         scanf("%lld",&x);         tr[rt].sum=x;         return;     }     int mid=(l+r)>>1;     build(rt<<1,l,mid);     build(rt<<1|1,mid+1,r);     tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; } inline void update(int rt,int L,int R,int x) {     int l=tr[rt].l,r=tr[rt].r;     if(L<=l && r<=R)     {         tr[rt].sum=(long long)x*(r-l+1)+tr[rt].sum;         tr[rt].add+=x;         return;     }     int len=(r-l+1);     if(tr[rt].add)     {         tr[rt<<1].add+=tr[rt].add;         tr[rt<<1|1].add+=tr[rt].add;         tr[rt<<1].sum+=(long long)tr[rt].add*(len-(len>>1));         tr[rt<<1|1].sum+=(long long)tr[rt].add*(len>>1);         tr[rt].add=0;     }     int mid=(l+r)>>1;     if(L<=mid)    update(rt<<1,L,R,x);     if(R>mid)    update(rt<<1|1,L,R,x);     tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; } inline long long query(int rt,int L,int R) {     int l=tr[rt].l,r=tr[rt].r;     if(L<=l && r<=R)     {         return    tr[rt].sum;     }     int len=(r-l+1);     if(tr[rt].add)     {         tr[rt<<1].add+=tr[rt].add;         tr[rt<<1|1].add+=tr[rt].add;         tr[rt<<1].sum+=(long long)tr[rt].add*(len-(len>>1));         tr[rt<<1|1].sum+=(long long)tr[rt].add*(len>>1);         tr[rt].add=0;     };     long long ret=0;     int mid=(l+r)>>1;     if(L<=mid)    ret+=(long long)query(rt<<1,L,R);     if(R>mid)    ret+=(long long)query(rt<<1|1,L,R);     return ret; } int main() {     int n,m,op,x,y,L,R;     scanf("%d%d",&n,&m);     build(1,1,n);      for(int i=1;i<=m;i++)     {         scanf("%d",&op);         if(op==1)         {             scanf("%d%d%d",&L,&R,&x);             update(1,L,R,x);         }         else         {             scanf("%d%d",&L,&R);             printf("%lld\n",query(1,L,R));         }     }     return 0; }

转载请注明原文地址: https://www.6miu.com/read-53349.html

最新回复(0)