1. 程式人生 > >【模板】非旋轉Treap

【模板】非旋轉Treap

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); } } }