代码复杂度较高的数据结构……写过的最长的模板(你才写过几个模板啊)
这么个东西:
线段树是棵平衡二叉树qwq 所以我们可以用\(i*2\)与\(i*2+1\)分别表示\(i\)的左儿子和右儿子
有点类似分块的思想 or 树状数组……???也是拆分拆分拆分求和求和求和
设置add的标记,省去一个个节点修改的很多时间
在修改&查询中不断维护父子关系
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
#define MAXN 1000001
#define leftson cur<<1
#define rightson cur<<1|1
#define mid ((l+r)>>1)
#define push_up ans[cur]=ans[leftson]+ans[rightson]
#define push_down lazyadd(leftson,l,mid,tag[cur]); lazyadd(rightson,mid+1,r,tag[cur]); tag[cur]=0
using namespace std;
ll ans[MAXN<<2],tag[MAXN<<2];
void build(ll cur,ll l,ll r)
{
if (l==r)
{
scanf("%lld",&ans[cur]);
return;
}
build(leftson,l,mid);
build(rightson,mid+1,r);
push_up;
}
inline void lazyadd(ll cur,ll l,ll r,ll delta)
{
tag[cur]+=delta;
ans[cur]+=delta*(r-l+1);
}
inline void change(ll adl,ll adr,ll cur,ll l,ll r,ll delta)
{
if (adl<=l&&r<=adr)
{
ans[cur]+=delta*(r-l+1);
tag[cur]+=delta;
return;
}
push_down;
if (adl<=mid) change(adl,adr,leftson,l,mid,delta);
if (adr>mid) change(adl,adr,rightson,mid+1,r,delta);
push_up;
}
long long query(ll quel,ll quer,ll cur,ll l,ll r)
{
if (quel<=l&&r<=quer)
{
return ans[cur];
}
push_down;
ll answer=0;
if (quel<=mid)
{
answer+=query(quel,quer,leftson,l,mid);
}
if (quer>mid)
{
answer+=query(quel,quer,rightson,mid+1,r);
}
return answer;
}
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
int cs;
build(1,1,n);
ll a,b,c;
for (ll i=1;i<=m;i++)
{
scanf("%d",&cs);
if (cs==1)
{
scanf("%lld%lld%lld",&a,&b,&c);
change(a,b,1,1,n,c);
continue;
}
scanf("%lld%lld",&a,&b);
printf("%lld\n",query(a,b,1,1,n));
}
return 0;
}