laplace_oo @ 2022-10-29 08:05:18
/// @brief FHQ Treap
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m,a[N];
int root,cnt;
int lc[N],rc[N],siz[N];
int val[N],sum[N],key[N],tag[N];
void add(int p,int k)
{
sum[p]+=siz[p]*k;
tag[p]+=k;
val[p]+=k;
}
void up(int p)
{
siz[p]=siz[lc[p]]+siz[rc[p]]+1;
sum[p]=sum[lc[p]]+sum[rc[p]]+val[p];
}
int neo(int v)
{
cnt++;
val[cnt]=v;
key[cnt]=rand();
siz[cnt]=1;
return cnt;
}
void dwd(int p)
{
if(lc[p])
{
sum[lc[p]]+=siz[lc[p]]*tag[p];
val[lc[p]]+=tag[p];
tag[lc[p]]+=tag[p];
}
if(rc[p])
{
sum[rc[p]]+=siz[rc[p]]*tag[p];
val[rc[p]]+=tag[p];
tag[rc[p]]+=tag[p];
}
tag[p]=0;
}
void split(int p,int &x,int &y,int k)
{
if(!p)
{
x=y=0;
return;
}
dwd(p);
if(siz[lc[p]]+1<=k)
{
x=p;
split(rc[p],rc[x],y,k-siz[lc[p]]-1);
}
else
{
y=p;
split(lc[p],x,lc[y],k);
}
up(p);
}
int merge(int x,int y)
{
if(!x||!y)return x|y;
dwd(x);
dwd(y);
if(key[x]<=key[y])
{
rc[x]=merge(rc[x],y);
up(x);
return x;
}
else
{
lc[y]=merge(x,lc[y]);
up(y);
return y;
}
}
int build(int l,int r)
{
if(l==r)return neo(a[l]);
int mid=(l+r)>>1;
return merge(build(l,mid),build(mid+1,r));
}
void addrange(int l,int r,int k)
{
int x,y,z;
split(root,x,y,r);
split(x,x,z,l-1);
add(z,k);
root=merge(x,merge(z,y));
}
int askrange(int l,int r)
{
int x,y,z;
split(root,x,y,r);
split(x,x,z,l-1);
int res=sum[z];
root=merge(x,merge(z,y));
return res;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
}
root=build(1,n);
for(int i=1;i<=m;++i)
{
int o,x,y;
scanf("%lld%lld%lld",&o,&x,&y);
if(o==1)
{
int k;
scanf("%lld",&k);
addrange(x,y,k);
}
else
{
printf("%lld\n",askrange(x,y));
}
}
return 0;
}
by 淸梣ling @ 2022-10-29 08:21:32
你可以尝试线段树
by 淸梣ling @ 2022-10-29 08:28:36
@Lake____ 你 neo sum
没更新
by laplace_oo @ 2022-10-29 08:41:40
@淸梣ling 过了,谢谢