题目大意
有个序列,一开始有n个元素
∙merge x e: 删掉第x+1个数并将第i个数改为
∙insert x e: 在第x个数后面插入一个
∙max x y: 询问当前区间[x,y]内任意长度大于1的子区间中极差的最大值
操作数为
1≤n,q≤105,1≤e,Ei≤109
题目分析
显然max询问就是最大值减最小值,min询问就是相邻的差的最小值。
直接使用splay维护就好了,min询问的维护要想好,不然挺坑的。
时间复杂度O(nlogn)。
代码实现
#include <iostream>
#include <climits>
#include <cstdio>
#include <cctype>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
int buf[30];
inline void write(int x)
{
if (x<0) putchar('-'),x=-x;
for (;x;x/=10) buf[++buf[0]]=x%10;
if (!buf[0]) buf[++buf[0]]=0;
for (;buf[0];putchar('0'+buf[buf[0]--]));
}
const int INF=INT_MAX;
const int N=100050;
const int Q=100050;
const int S=N+Q;
int e[N];
int n,q;
inline int abs(int x){return x>0?x:-x;}
struct SPLAY
{
int son[S][2],fa[S],size[S],E[S],R[S],D[S],f[S][2],g[S];//E energy R right element D diff
int tot,root;
inline bool side(int x){return son[fa[x]][1]==x;}
inline void update(int x)
{
if (!x) return;
size[x]=size[son[x][0]]+size[son[x][1]]+1;
R[x]=son[x][1]?R[son[x][1]]:E[x],g[x]=min(D[x],min(g[son[x][0]],g[son[x][1]]));
f[x][0]=min(E[x],min(f[son[x][0]][0],f[son[x][1]][0])),f[x][1]=max(E[x],max(f[son[x][0]][1],f[son[x][1]][1]));
}
inline int newnode(int x,int y,int l,int r)
{
fa[++tot]=0,E[tot]=x,D[tot]=y;
fa[l]=l?tot:0,fa[r]=r?tot:0,son[tot][0]=l,son[tot][1]=r;
return update(tot),tot;
}
inline void rotate(int x)
{
int y=fa[x];bool s=side(x);
if (fa[y]) son[fa[y]][side(y)]=x;
if (son[x][s^1]) fa[son[x][s^1]]=y;
son[y][s]=son[x][s^1],son[x][s^1]=y;
fa[x]=fa[y],fa[y]=x;
update(y),update(x);
}
inline void splay(int x,int y)
{
for (;fa[x]!=y;rotate(x))
if (fa[fa[x]]!=y)
if (side(x)==side(fa[x])) rotate(fa[x]);
else rotate(x);
}
inline int kth(int x,int y)
{
if (size[son[x][0]]+1==y) return x;
return size[son[x][0]]>=y?kth(son[x][0],y):kth(son[x][1],y-size[son[x][0]]-1);
}
inline void split(int x,int y,int &l,int &r)
{
if (!y) l=0,r=x;
else splay(l=kth(x,y),0),r=son[l][1],son[l][1]=fa[r]=0,update(l);
}
inline void merge(int x,int y,int &rt)
{
if (!x) rt=y;
else if (!y) rt=x;
else splay(rt=kth(x,size[x]),0),son[fa[y]=rt][1]=y,update(rt);
}
inline int query(int l,int r,bool tp)
{
int x,y,mid,ret;
split(root,r,x,y),split(x,l-(tp^1),x,mid),ret=tp?g[mid]:f[mid][1]-f[mid][0],merge(x,mid,x),merge(x,y,root);
return ret;
}
inline void insert(int x,int y)
{
int l,r;
split(root,x,l,r),splay(r=kth(r,1),0),D[r]=abs(E[r]-y),update(r),root=newnode(y,abs(y-E[l]),l,r);
}
inline void extend(int x,int y)
{
int l,r;
split(root,x,l,r);
if (size[r]>1) splay(r=kth(r,2),0),fa[son[l][1]=r]=l,E[l]=y,D[l]=abs(E[l]-R[son[l][0]]),son[r][0]=0,D[r]=abs(E[l]-E[r]),update(r);
update(root=l);
}
inline void init()
{
tot=0,E[tot]=R[tot]=g[tot]=f[tot][0]=INF,e[0]=INF;
for (int i=1;i<=n;++i) root=newnode(e[i],abs(e[i]-e[i-1]),root,0);
//splay(1,0),root=1;
}
}t;
int main()
{
freopen("atom.in","r",stdin),freopen("atom.out","w",stdout);
n=read(),q=read();
for (int i=1;i<=n;++i) e[i]=read();
for (t.init();q--;)
{
char opt=getchar();
while (!isalpha(opt)) opt=getchar();
if (opt=='m')
{
opt=getchar();
int x=read(),y=read();
switch (opt)
{
case 'e':
{
t.extend(x,y);
break;
}
case 'a':
{
write(t.query(x,y,0)),putchar('\n');
break;
}
case 'i':
{
write(t.query(x,y,1)),putchar('\n');
break;
}
}
}
else
{
int x=read(),e=read();
t.insert(x,e);
}
}
fclose(stdin),fclose(stdout);
return 0;
}