题目链接:
题意:给出一个数列,初始时有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;}