下传标记
void back(ll x,ll y){
a[x]+=y,ans[x]+=y,add[x]+=y;
}
更新当前点的答案
void update(ll x){
ans[x]=max(a[x],max(ans[tr[x][0]],ans[tr[x][1]]));
}
把标记传给儿子
void clear(ll x){
if (tr[x][0]) back(tr[x][0],add[x]);
if (tr[x][1]) back(tr[x][1],add[x]);
add[x]=0;
}
判断点x是它父亲的左儿子还是右儿子
ll son(ll x){
return tr[fa[x]][1]==x;
}
把x旋到x的父亲
void rotate(ll x){
ll k=son(x),y=fa[x];
if (tr[x][!k]) fa[tr[x][!k]]=y;
if (fa[y]) tr[fa[y]][son(y)]=x;
fa[x]=fa[y],fa[y]=x,tr[y][k]=tr[x][!k],tr[x][!k]=y;
update(y),update(x);
}
释放从x到y的标记
void remove(ll x,ll y){
d[0]=0;
while (x!=y){
d[++d[0]]=x,x=fa[x];
}
while (d[0]) clear(d[d[0]--]);
}
把x旋到y的儿子
void splay(ll x,ll y){
remove(x,y);
while (fa[x]!=y){
if (fa[fa[x]]!=y)
rotate((son(x)==son(fa[x]))?fa[x]:x);
rotate(x);
}
}
查找排名为x的点
ll find(ll x){
ll rk=0,nw=rt;
while (1){
if (tr[nw][0] && siz[tr[nw][0]]+rk>=x) nw=tr[nw][0];else{
rk+=siz[tr[nw][0]];
if (rk+1==x){
splay(nw,0);
rt=nw;
return nw;
}
rk+=1,nw=tr[nw][1];
}
}
}
查询区间x,y
if (ch=='Q'){
scanf("uery%lld%lld\n",&l,&r);
l++,r++;
x=find(l-1);
y=find(r+1);
splay(x,0);
rt=x;
splay(y,x);
printf("%lld\n",(ans[tr[y][0]]+mo)%mo);
}
在区间x,y中+z
if (ch=='A'){
scanf("dd%lld%lld%lld\n",&l,&r,&z);
l++,r++;
x=find(l-1),y=find(r+1);
splay(x,0),splay(y,x);
rt=x;
back(tr[y][0],z);
}
在x前插入y
if (ch=='I'){
scanf("nsert%lld%lld\n",&l,&r);
x=find(l);
y=find(l+1);
splay(x,0),splay(y,x);
rt=x;
tr[y][0]=++n;
fa[n]=y;
a[n]=r;
p[n]=r*r%mo;
update(n);
splay(n,0);
rt=n;
}