bzoj 1058 bst
因为是数列的维护,所以我们可以考虑用splay来维护,每次在x插入的时候就在x+1前面插入就行了,然后用bst来维护两问的答案,但是应该会tle。我们来考虑这个问题的性质,首先因为这个数列没有删除操作,所以每个数插入进去之后就不会出来了,换句话说,就是假设insert(x,y)那么y这个值和前面的那个数可以更新相邻差值的答案,且这个不会因为其他的插入操作而使得这个差值消失(消失值类似(x,y)插入,那么之前在x处插入的点与x+1的差值会消失),所以我们只需要存储每个位置最后插入的数,那么对于一个插入(x,y)我们只需要判断x位置是否插入过值然后讨论就行了。那么对于另一个全局差值的更新我们只需要用bst维护所有插入的数,每插入一个数就找前驱后继来更新答案就行了。因为这个答案是递减的,所以当答案为0的时候不用更新就行了,这样大概可以快3-4s。
反思:很早的时候用pascal写了splay的,满满的tle,然后转了C++之后用的set和map,快了好多,也好写了好多= =
/************************************************************** Problem: 1058 User: BLADEVIL Language: C++ Result: Accepted Time:9924 ms Memory:40700 kb ****************************************************************/ //By BLADEVIL #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <set> #define maxn 1000010 #define inf (~0U>>1) using namespace std; int n,m,ans; int a[maxn],b[maxn]; char c[20]; map<int,int>ms; set<int>bt; void update(int x){ if (bt.count(x)) { ans=0; return; } set<int>::iterator p=bt.upper_bound(x); if (p!=bt.end()) ans=min(ans,abs(*p-x));//,printf("%d->%d ",x,*p); --p; if (*p!=-inf) ans=min(ans,abs(*p-x));//,printf("%d<-%d",x,*p); printf("\n"); bt.insert(x); } void insert(int x){ map<int,int>::iterator p=ms.find(x); if (p!=ms.end()) p->second++; else ms.insert(pair<int,int>(x,1)); } void erase(int x){ map<int,int>::iterator p=ms.find(x); if (p->second==1) ms.erase(p); else p->second--; } void printbt(){ for (set<int>::iterator p=bt.begin();p!=bt.end();p++) printf("%d ",*p); printf("\n"); } void printms(){ for (map<int,int>::iterator p=ms.begin();p!=ms.end();p++) printf("|%d %d\n",p->first,p->second); } int main(){ ans=inf; bt.insert(-inf); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<n;i++) insert(abs(a[i]-a[i+1])); for (int i=1;i<=n;i++) { if (bt.count(a[i])) { ans=0; break; } update(a[i]); } //printms(); printbt(); while (m--){ scanf("%s",&c); if (c[0]=='I'){ int x,y; scanf("%d%d",&x,&y); if (x==n){ if (b[x]) insert(abs(b[x]-y)); else insert(abs(a[x]-y)); } else { if (b[x]){ erase(abs(b[x]-a[x+1])); insert(abs(b[x]-y)); insert(abs(a[x+1]-y)); } else { erase(abs(a[x]-a[x+1])); insert(abs(a[x]-y)); insert(abs(a[x+1]-y)); } } b[x]=y; if (ans) update(y); } else if (c[4]=='G') { printf("%d\n",ms.begin()->first); } else printf("%d\n",ans); } return 0; }
/************************************************************** Problem: 1058 User: BLADEVIL Language: Pascal Result: Time_Limit_Exceed ****************************************************************/ //By BLADEVIL var n, m :longint; root, sroot :longint; father, size :array[-1..1000010] of longint; tree, a :array[-1..1000010] of int64; son :array[-1..1000010,0..1] of longint; numt, t, st :longint; tot :longint; left, right, b_size :array[0..4000010] of longint; key :array[0..4000010] of int64; print :int64; function abs(x:int64):int64; begin if x<0 then exit(-x) else exit(x); end; function min(a,b:int64):int64; begin if a>b then min:=b else min:=a; end; procedure update(x:longint); begin size[x]:=size[son[x][0]]+size[son[x][1]]+1; end; function build(l,r:longint):longint; var mid :longint; begin mid:=(l+r)>>1; build:=mid; tree[mid]:=a[mid]; if mid-1>=l then begin son[mid][0]:=build(l,mid-1); father[son[mid][0]]:=mid; end; if mid+1<=r then begin son[mid][1]:=build(mid+1,r); father[son[mid][1]]:=mid; end; update(mid); end; procedure rotate(x,y:longint); var f :longint; begin f:=father[x]; son[f][y]:=son[x][y xor 1]; father[son[x][y xor 1]]:=f; if f=root then root:=x else if f=son[father[f]][0] then son[father[f]][0]:=x else if f=son[father[f]][1] then son[father[f]][1]:=x; son[x][y xor 1]:=f; father[x]:=father[f]; father[f]:=x; update(f); update(x); end; procedure splay(x,y:longint); var u, v :longint; begin while father[x]<>y do if father[father[x]]=y then rotate(x,ord(x=son[father[x]][1])) else begin if x=son[father[x]][0] then u:=1 else u:=-1; if father[x]=son[father[father[x]]][0] then v:=1 else v:=-1; if u*v=1 then begin rotate(father[x],ord(x=son[father[x]][1])); rotate(x,ord(x=son[father[x]][1])); end else begin rotate(x,ord(x=son[father[x]][1])); rotate(x,ord(x=son[father[x]][1])); end; end; update(x); end; function find(x:int64):int64; var t :longint; begin t:=root; while true do begin if size[son[t][0]]+1=x then exit(t) else if size[son[t][0]]+1>x then t:=son[t][0] else begin x:=x-(size[son[t][0]]+1); t:=son[t][1]; end; end; end; procedure left_rotate(var t:longint); var k :longint; begin k:=right[t]; right[t]:=left[k]; left[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[left[t]]+b_size[right[t]]+1; t:=k; end; procedure right_rotate(var t:longint); var k :longint; begin k:=left[t]; left[t]:=right[k]; right[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[left[t]]+b_size[right[t]]+1; t:=k; end; procedure maintain(var t:longint;flag:boolean); begin if not flag then begin if b_size[left[left[t]]]>b_size[right[t]] then right_rotate(t) else if b_size[right[left[t]]]>b_size[right[t]] then begin left_rotate(left[t]); right_rotate(t); end else exit; end else begin if b_size[right[right[t]]]>b_size[left[t]] then left_rotate(t) else if b_size[left[right[t]]]>b_size[left[t]] then begin right_rotate(right[t]); left_rotate(t); end else exit; end; maintain(left[t],false); maintain(right[t],true); maintain(t,true); maintain(t,false); end; procedure insert(var t:longint;v:int64); begin if t=0 then begin inc(tot); t:=tot; key[t]:=v; b_size[t]:=1; left[t]:=0; right[t]:=0; end else begin b_size[t]:=b_size[t]+1; if v<key[t] then insert(left[t],v) else insert(right[t],v); maintain(t,v>=key[t]); end; end; function pred(var t:longint;v:int64):int64; begin if t=0 then exit(maxlongint>>1); if key[t]>v then pred:=pred(left[t],v) else begin pred:=pred(right[t],v); if pred=maxlongint>>1 then exit(key[t]); end; end; function succ(var t:longint;v:int64):int64; begin if t=0 then exit(maxlongint>>1); if key[t]<v then succ:=succ(right[t],v) else begin succ:=succ(left[t],v); if succ=maxlongint>>1 then exit(key[t]); end; end; function delete(var t:longint;v:int64):int64; begin b_size[t]:=b_size[t]-1; if (key[t]=v) or (v>key[t]) and (right[t]=0) or (v<key[t]) and (left[t]=0) then begin delete:=key[t]; if (left[t]=0) or (right[t]=0) then t:=left[t]+right[t] else key[t]:=delete(left[t],v+1); end else if v>=key[t] then delete:=delete(right[t],v) else delete:=delete(left[t],v); end; procedure change(x:longint;y:int64); var q, p :int64; begin splay(x,sroot); p:=size[son[root][0]]; p:=find(p); splay(p,root); delete(t,abs(tree[p]-tree[root])); insert(t,abs(y-tree[p])); insert(t,abs(y-tree[root])); inc(n); a[n]:=y; tree[n]:=y; son[son[root][0]][1]:=n; father[n]:=son[root][0]; size[n]:=1; update(son[root][0]); update(root); p:=pred(numt,y); q:=succ(numt,y); if p=maxlongint>>1 then insert(st,abs(q-y)) else if q=maxlongint>>1 then insert(st,abs(p-y)) else insert(st,min(abs(p-y),abs(q-y))); insert(numt,y); end; function mini(var t:longint):int64; begin if left[t]=0 then exit(key[t]) else exit(mini(left[t])); end; procedure init; var i :longint; x, y :int64; begin readln(n,m); for i:=1 to n do read(a[i]); readln; numt:=0; st:=0; for i:=1 to n do begin x:=succ(numt,a[i]); y:=pred(numt,a[i]); insert(numt,a[i]); if x=maxlongint>>1 then insert(st,abs(y-a[i])) else if y=maxlongint>>1 then insert(st,abs(x-a[i])) else insert(st,min(abs(x-a[i]),abs(y-a[i]))); end; t:=0; for i:=1 to n-1 do insert(t,abs(a[i+1]-a[i])); fillchar(son,sizeof(son),255); sroot:=-1; inc(n); root:=build(0,n); father[root]:=sroot; end; procedure main; var i :longint; s :ansistring; ch :char; x :longint; y :int64; begin print:=maxlongint>>1; for i:=1 to m do begin read(ch); if ch='I' then begin s:=''; while ch<>' ' do begin s:=s+ch; read(ch); end; readln(x,y); change(x+1,y); end else begin readln(s); if s[4]='S' then begin if print=0 then begin writeln(0); end else begin if mini(st)<print then print:=mini(st); writeln(print); end; end else writeln(mini(t)); end; end; end; begin init; main; end.