【模板】非旋轉Treap
阿新 • • 發佈:2018-12-21
Code
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 100005
#define LL long long
using namespace std;
int n1,t[N][2],key[N],q,n,rt,st[N];
LL vl[N],sm[N],lz[N],sz[N];
void upd(int k,LL v)
{
if(k) lz[k]+=v,sm[k]+=v*sz[k],vl[k]+=v;
}
void down(int k)
{
upd(t[k][0],lz[k]),upd(t[k][1],lz[k]);
lz[k]=0;
}
void up(int k)
{
sz[k]=sz[t[k][0]]+sz[t[k][1]]+1;
sm[k]=sm[t[k][0]]+sm[t[k][1]]+vl[k];
}
void split( int &k,int &x,int v)
{
if(!k) {x=0;return;}
down(k);
if(sz[t[k][0]]>=v) split(t[k][0],x,v),swap(t[k][0],x),up(k),swap(k,x);
else split(t[k][1],x,v-sz[t[k][0]]-1),up(k);
}
int merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
down(x),down(y);
if(key[x]<=key[y]) {t[x][1]=merge(t[ x][1],y);up(x);return x;}
else {t[y][0]=merge(x,t[y][0]);up(y);return y;}
}
int build()
{
int top=1;
key[0]=-2147483647;
fo(i,1,n)
{
while(top&&key[st[top]]>key[i]) up(st[top]),st[top--]=0;
t[i][0]=t[st[top]][1],t[st[top]][1]=i;
st[++top]=i;
}
fod(i,top,2) up(st[i]);
key[0]=sz[0]=sm[0]=vl[0]=t[0][1]=t[0][0]=0;
return st[2];
}
int main()
{
cin>>n>>q;
srand(13271815);
fo(i,1,n) scanf("%lld",&vl[i]),key[i]=rand()*rand()-rand();
rt=build();
fo(i,1,q)
{
int p,x,y,u=rt,v,w;
LL z;
scanf("%d%d%d",&p,&x,&y);
if(p==1)
{
scanf("%lld",&z);
split(u,v,x-1);
split(v,w,y-x+1);
upd(v,z);
u=merge(u,v),rt=merge(u,w);
}
else
{
split(u,v,x-1);
split(v,w,y-x+1);
printf("%lld\n",sm[v]);
u=merge(u,v),rt=merge(u,w);
}
}
}