题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1058
题意:给出一个数列,初始时有n个数字。三种操作:(1)在第i个之后插入数字k,(1<=i<=n),注意这里的插入,这个n就是一开始的n,不是当前数列的长度。比如若在第i个之后插入数字x,又再第i个数字之后插入y,那么y要插在x的后面;(2)询问数列中相邻两项差值的最小值;(3)询问整个数列所有数中差值的最小值。
思路:(1)首先,第二种询问比较容易解决,只要将所有数字插入到set中,每次找与当前数字最近的两个比较即可;并且显然这个值只会递减不会增加;
(2)对于第一种查询我使用splay实现,节点保存当前节点的val以及以当前节点为根的子树的区间的两个端点的值Lval和Rval,以及相邻数字的最小值Min。每次更新即可。
struct node
{
i64 val,Lval,Rval,Min;
int size;
node *p,*c[2];
};
node a[N],*nullNode,*root,*x1,*x2;
int cnt;
node *newNode(i64 val,node *p)
{
node *e=&a[cnt++];
e->c[0]=e->c[1]=nullNode;
e->p=p;
e->val=e->Lval=e->Rval=val;
e->Min=inf;
e->size=1;
return e;
}
void pushUp(node *p)
{
if(p==nullNode) return;
p->size=1+p->c[0]->size+p->c[1]->size;
p->Min=inf;
if(p->c[0]!=x1&&p->c[0]!=x2&&p->c[0]!=nullNode)
{
p->Min=min(abs(p->val-p->c[0]->Rval),p->c[0]->Min);
p->Lval=p->c[0]->Lval;
}
else p->Lval=p->val;
if(p->c[1]!=x1&&p->c[1]!=x2&&p->c[1]!=nullNode)
{
p->Min=min(p->Min,min(abs(p->val-p->c[1]->Lval),p->c[1]->Min));
p->Rval=p->c[1]->Rval;
}
else p->Rval=p->val;
}
void init()
{
cnt=0;
nullNode=0;
nullNode=newNode(0,nullNode);
nullNode->size=0;
root=newNode(inf,nullNode);
root->c[1]=newNode(inf,root);
pushUp(root);
x1=root;
x2=root->c[1];
}
void zig(node *x)
{
node *p=x->p,*q=p->p;
p->c[0]=x->c[1];
if(x->c[1]!=nullNode) x->c[1]->p=p;
x->c[1]=p;
p->p=x;
if(q!=nullNode)
{
if(q->c[0]==p) q->c[0]=x;
else q->c[1]=x;
}
x->p=q;
pushUp(p);
pushUp(x);
if(root==p) root=x;
}
void zag(node *x)
{
node *p=x->p,*q=p->p;
p->c[1]=x->c[0];
if(x->c[0]!=nullNode) x->c[0]->p=p;
x->c[0]=p;
p->p=x;
if(q!=nullNode)
{
if(q->c[0]==p) q->c[0]=x;
else q->c[1]=x;
}
x->p=q;
pushUp(p);
pushUp(x);
if(root==p) root=x;
}
void splay(node *x,node *goal)
{
while(x->p!=goal)
{
if(x->p->p!=goal)
{
if(x->p->p->c[0]==x->p)
{
if(x->p->c[0]==x) zig(x->p),zig(x);
else zag(x),zig(x);
}
else
{
if(x->p->c[1]==x) zag(x->p),zag(x);
else zig(x),zag(x);
}
}
else
{
if(x->p->c[0]==x) zig(x);
else zag(x);
}
}
}
void select(int k,node *goal)
{
node *x=root;
while(k!=1+x->c[0]->size)
{
if(k<=x->c[0]->size) x=x->c[0];
else
{
k-=1+x->c[0]->size;
x=x->c[1];
}
}
splay(x,goal);
}
i64 ans1,ans2;
set<i64> s;
void insert(int k,i64 val)
{
select(k+1,nullNode);
select(k+2,root);
node *p=newNode(val,root->c[1]);
root->c[1]->c[0]=p;
splay(root->c[1]->c[0],nullNode);
ans1=root->Min;
if(ans2==0) return;
set<i64>::iterator it;
it=s.lower_bound(val);
if(it!=s.end())
{
if(abs(*it-val)<ans2) ans2=abs(*it-val);
}
if(it!=s.begin())
{
it--;
if(abs(*it-val)<ans2) ans2=abs(*it-val);
}
s.insert(val);
}
int n,m;
int S[N];
void add(int x)
{
while(x<N)
{
S[x]++;
x+=x&-x;
}
}
int get(int x)
{
int ans=0;
while(x)
{
ans+=S[x];
x-=x&-x;
}
return ans;
}
int main()
{
init(); RD(n,m); ans1=ans2=inf;
int i;
i64 x;
FOR1(i,n)
{
RD(x);
insert(get(i),x);
add(i);
}
char op[20];
int pos;
i64 val;
while(m--)
{
RD(op);
if(op[0]=='I')
{
RD(pos);
RD(val);
insert(get(pos),val);
add(pos);
}
else if(op[4]=='G') PR(ans1);
else PR(ans2);
}
return 0;
}