P7549 [BJWC2017] 神秘物质
\text{Solution}
插入一个新能源和合并成为一个新的就文艺平衡树基本操作,分裂出对应区间,合并就先删除掉以前的,之后再插入。 max 的话维护下子树最大值和最小值即可。但 min 怎么维护?
我们加入插进来数 x ,原来有 a , b 两数。
则原来:
如何在 fhq 上维护相邻的数呢? 只需要记录下子树向左/右能最远扩展到的值即可。 那么当前左边的数是不是左子树向右最远扩展的值,右边同理。
\text{Code}
#include <bits/stdc++.h>
#define N (int)(1e5+5)
#define int long long
#define inf (int)(2e18)
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
struct FHQ {
int ls,rs,val,rad,sz,lres,rres,mires,mx,mi;
FHQ() {
ls=rs=val=rad=sz=lres=rres=mires=mx=mi=0;
}
}t[N<<2];
int tot,rt;
void push_up(int cur) {
int ls=t[cur].ls,rs=t[cur].rs;
t[cur].sz=t[ls].sz+t[rs].sz+1;
t[cur].mx=t[cur].mi=t[cur].lres=t[cur].rres=t[cur].val;
t[cur].mires=inf;
if(ls) {
t[cur].mi=min(t[cur].mi,t[ls].mi);
t[cur].mx=max(t[cur].mx,t[ls].mx);
t[cur].lres=t[ls].lres;
t[cur].mires=min(t[cur].mires,min(abs(t[ls].rres-t[cur].val),t[ls].mires));
}
if(rs) {
t[cur].mi=min(t[cur].mi,t[rs].mi);
t[cur].mx=max(t[cur].mx,t[rs].mx);
t[cur].rres=t[rs].rres;
t[cur].mires=min(t[cur].mires,min(abs(t[rs].lres-t[cur].val),t[rs].mires));
}
}
void split(int cur,int num,int &x,int &y) {
if(!cur) return x=y=0,void();
if(t[t[cur].ls].sz+1<=num) {
x=cur;
split(t[cur].rs,num-t[t[cur].ls].sz-1,t[cur].rs,y);
} else {
y=cur;
split(t[cur].ls,num,x,t[cur].ls);
}
push_up(cur);
}
int merge(int x,int y) {
if(!x||!y) return x+y;
if(t[x].rad<t[y].rad) {
t[x].rs=merge(t[x].rs,y);
push_up(x); return x;
} else {
t[y].ls=merge(x,t[y].ls);
push_up(y); return y;
}
}
int newp(int x) {
++tot; t[tot].rad=rand(); t[tot].val=x; t[tot].sz=1; t[tot].mires=inf;
t[tot].mi=t[tot].mx=t[tot].rres=t[tot].lres=x;
return tot;
}
void ins(int pos,int v) {
int r1,r2;
split(rt,pos,r1,r2);
rt=merge(merge(r1,newp(v)),r2);
}
void remerge(int pos,int v) {
int r1,r2,r3;
split(rt,pos+1,r1,r2); split(r1,pos-1,r1,r3);
rt=merge(merge(r1,newp(v)),r2);
}
int query1(int l,int r) {
int r1,r2,r3,res;
split(rt,r,r2,r1); split(r2,l-1,r3,r2);
res=t[r2].mx-t[r2].mi;
rt=merge(merge(r3,r2),r1);
return res;
}
int query2(int l,int r) {
int r1,r2,r3,res;
split(rt,r,r2,r1); split(r2,l-1,r3,r2);
res=t[r2].mires;
rt=merge(merge(r3,r2),r1);
return res;
}
void DEBUG(int cur) {
if(t[cur].ls) DEBUG(t[cur].ls);
cout<<t[cur].val<<endl;
if(t[cur].rs) DEBUG(t[cur].rs);
}
signed main() {
srand(998244353); //srand((rand()<<3)*(rand()<<2));
++tot; t[1].val=inf; t[1].mi=inf; t[1].mx=-1; t[1].mires=inf;
int n,m,x,y; char op[10]; n=rd(); m=rd();
for(int i=1;i<=n;i++) {
x=rd(); ins(i-1,x);
}
// DEBUG(rt);
while(m--) {
scanf("%s",op); x=rd(); y=rd();
if(op[1]=='e') {
remerge(x,y);
} else if(op[1]=='n') {
ins(x,y);
} else if(op[1]=='a') {
printf("%lld\n",query1(x,y));
} else if(op[1]=='i') {
printf("%lld\n",query2(x,y));
}
}
return 0;
}