题意
给一个序列,要求资瓷如下操作:
merge x e 当前第 x 个元素和第 x+1 个元素合并,得到权值为 e 的新元素;
insert x e 在当前第 x 个元素和第 x+1 个元素之间插入一个权值为 e 的新元素。
max x y 当前第 x 到第 y 个元素之间的任意子区间中区间极差的最大值;
min x y 当前第 x 到第 y 个元素之间的任意子区间中区间极差的最小值。
n,m<=100000,a[i]<=10^9
分析
要求插入删除的话,线段树就不能做了吧。于是我们就可以上平衡树了。但由于要求区间查询,于是我们只能选择splay或可持久化treap了。我用的是splay。
最大极差的话就维护最大最小值就好了。
最小极差的话就维护相邻两点的最小值就好了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=100005;
const int inf=1e9;
int n,m,tot,a[N],root;
struct tree{int ans,mn,mx,val1,val2,l,r,fa,size;}t[N*2];
void updata(int x)
{
t[x].mx=max(t[x].val1,max(t[t[x].l].mx,t[t[x].r].mx));
t[x].mn=min(t[x].val1,min(t[t[x].l].mn,t[t[x].r].mn));
t[x].ans=min(t[x].val2,min(t[t[x].l].ans,t[t[x].r].ans));
t[x].size=t[t[x].l].size+t[t[x].r].size+1;
}
void rttr(int x)
{
int y=t[x].l;
if (x==root) root=y;
t[x].l=t[y].r;t[t[y].r].fa=x;
if (x==t[t[x].fa].l) t[t[x].fa].l=y;
else if (x==t[t[x].fa].r) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;t[y].r=x;
updata(x);updata(y);
}
void rttl(int x)
{
int y=t[x].r;
if (x==root) root=y;
t[x].r=t[y].l;t[t[y].l].fa=x;
if (x==t[t[x].fa].l) t[t[x].fa].l=y;
else if (x==t[t[x].fa].r) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;t[y].l=x;
updata(x);updata(y);
}
void splay(int x,int y)
{
while (t[x].fa!=y)
{
int p=t[x].fa,g=t[p].fa;
if (g==y)
{
if (x==t[p].l) rttr(p);
else rttl(p);
return;
}
if (x==t[p].l)
if (p==t[g].l) rttr(g),rttr(p);
else rttr(p),rttl(g);
else
if (p==t[g].r) rttl(g),rttl(p);
else rttl(p),rttr(g);
}
}
int kth(int k)
{
if (k>t[root].size) return 0;
int x=root;
while (x)
{
if (t[t[x].l].size+1==k) return x;
if (t[t[x].l].size>=k) x=t[x].l;
else k-=t[t[x].l].size+1,x=t[x].r;
}
}
void ins(int pos,int val1,int val2)
{
t[++tot].val1=val1;t[tot].val2=val2;t[tot].size=1;
if (!root)
{
root=tot;return;
}
int x=kth(pos-1),y=kth(pos);
if (!t[x].r) t[tot].fa=x,t[x].r=tot;
else t[tot].fa=y,t[y].l=tot;
splay(tot,0);
}
void del(int x)
{
int y=t[x].l+t[x].r;
if (root==x) root=y;
if (x==t[t[x].fa].l) t[t[x].fa].l=y;
else t[t[x].fa].r=y;
if (y) t[y].fa=t[x].fa;
if (t[x].fa) splay(t[x].fa,0);
}
int main()
{
t[0].mn=t[0].ans=inf;t[0].mx=-inf;
scanf("%d%d",&n,&m);
ins(1,0,0);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) ins(i+1,a[i],abs(a[i]-a[i+1]));
ins(n+2,0,0);
while (m--)
{
char ch[10];int x,y;
scanf("%s%d%d",ch,&x,&y);
if (ch[1]=='e')
{
int p=kth(x+1),q=kth(x+2),w=kth(x+3),z=kth(x);
t[z].val2=abs(t[z].val1-y);splay(z,0);
if (!t[p].r) del(p),t[q].val1=y,t[q].val2=abs(y-t[w].val1),splay(q,0);
else del(q),t[p].val1=y,t[p].val2=abs(y-t[w].val1),splay(p,0);
}
else if (ch[0]=='i')
{
int q=kth(x+1);t[q].val2=abs(t[q].val1-y);splay(q,0);
if (x==t[root].size-2)
{
ins(x+2,y,0);continue;
}
int p=kth(x+2);
ins(x+2,y,abs(y-t[p].val1));
}
else if (ch[1]=='a')
{
int p=kth(x),q=kth(y+2);
splay(p,0);splay(q,p);
printf("%d\n",t[t[q].l].mx-t[t[q].l].mn);
}
else
{
int p=kth(x),q=kth(y+1);
splay(p,0);splay(q,p);
printf("%d\n",t[t[q].l].ans);
}
}
return 0;
}