1. 程式人生 > 實用技巧 >模板線段樹

模板線段樹

模板線段樹

來至洛谷網站

如題,已知一個數列,你需要進行下面兩種操作:

  1. 將某區間每一個數加上kk。
  2. 求出某區間每一個數的和。

輸入格式

第一行包含兩個整數n,,m,分別表示該數列數字的個數和操作的總個數。

第二行包含nn個用空格分隔的整數,其中第ii個數字表示數列第ii項的初始值。

接下來mm行每行包含344個整數,表示一個操作,具體如下:

  1. 1x y k:將區間[x, y][x,y]內每個數加上k
  2. 2x y:輸出區間[x, y][x,y]內每個數的和。

輸出格式

輸出包含若干行整數,即為所有操作 2 的結果。

輸入輸出樣例

如題,已知一個數列,你需要進行下面兩種操作:

  1. 將某區間每一個數加上kk。
  2. 求出某區間每一個數的和。

輸入格式

第一行包含兩個整數n,,m,分別表示該數列數字的個數和操作的總個數。

第二行包含nn個用空格分隔的整數,其中第ii個數字表示數列第ii項的初始值。

接下來m行每行包含3或4個整數,表示一個操作,具體如下:

  1. 1x y k:將區間[x, y][x,y]內每個數加上k
  2. 2x y:輸出區間[x, y][x,y]內每個數的和。

輸出格式

輸出包含若干行整數,即為所有操作 2 的結果。

輸入輸出樣例

#include<iostream>
#include<cstring>
using namespace std;
long long ans;

int add[100005];
int n,m,x,y,k,Q,i,mid;
int t=5;
struct rec{
int l,r;
long long dat;
}a[100005];
long long b[100005];
int Add(int p,int k)
{
add[p]+=k;
a[p].dat+=(a[p].r-a[p].l+1)*k;
}
void pushdown(int p)
{
if(add[p]==0)
return;
Add(p*2,add[p]);
Add(p*2+1,add[p]);
}
void build(int p,int L,int R)
{
a[p].l=L;
a[p].r=R;
if(L==R)
{
a[p].dat=b[L];
return;
}
mid=(L+R)/2;
build(p*2,L,mid);
build(p*2+1,mid+1,R);
a[p].dat=a[p*2].dat+a[p*2+1].dat;
t=t+1;
}
void change(int p,int L,int R,int k)
{
pushdown(p);
if((L<=a[p].l)&&(R>=a[p].r))
{
Add(p,k);
}
mid=(a[p].l+a[p].r)/2;
if(L<=mid)change(p*2,L,R,k);
if(R>mid)change(p*2+1,L,R,k);
}
long long ask(int p,int L,int R)
{
long long ans=0;
if((L<=a[p].l)&&(R>=a[p].r))
{
return a[p].dat;
}
pushdown(p);
mid=(a[p].l+a[p].r)/2;
if(L<=mid)ans+=ask(p*2,L,R);
if(R>mid)ans+=ask(p*2+1,L,R);
return ans;
}
int main()
{
cin>>n>>m;


for(i=1;i<=n;i++)
{
cin>>b[i];

}
build(1,1,n);

for(i=1;i<=m;i++)
{
cin>>Q;
if(Q==1)
{
cin>>x>>y>>k;
change(1,x,y,k);
}
else
{

cin>>x>>y;
ask(1,x,y);
cout<<ans<<endl;
}
}
}