【Luogu】P1110报表统计(Splay)
SBT,我居然没看出来。
就是插入的时候考虑向平衡树里插两个差值,删一个差值。
另一个操作就是维护某元素和其前驱后继的差值最小值就行了。
然后Splay超时了……
(貌似Splay超时了之后我都是修改splay操作的频率暴力硬卡,而不是考虑换一种思路……
然后就被我卡过了。
// luogu-judger-enable-o2 // luogu-judger-enable-o2 // luogu-judger-enable-o2 // luogu-judger-enable-o2 #include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<cstdlib> #define maxn 700010 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int CNT=0; struct Splay{ struct Node{ int val,fa,e[2],size,sum; }tree[maxn]; int point,tot,root; Splay(){point=tot=root=0; } inline void update(int x){ tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+tree[x].sum; } inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; } inline int iden(int x){ return x==tree[tree[x].fa].e[1]; } inline void rotate(int x){ int y=tree[x].fa;int r=tree[y].fa; if(y==root) root=x; int sony=iden(x);int sonr=iden(y); int b=tree[x].e[sony^1]; connect(b,y,sony); connect(y,x,sony^1); connect(x,r,sonr); update(y); update(x); } void splay(int pos,int to){ to=tree[to].fa; while(tree[pos].fa!=to){ if(tree[tree[pos].fa].fa==to) rotate(pos); else if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa); rotate(pos); } else{ rotate(pos); rotate(pos); } } } int create(int val,int fa){ tree[++tot].val=val; tree[tot].fa=fa; tree[tot].size=tree[tot].sum=1; return tot; } int build(int val){ point++; if(root==0){ root=create(val,0); return root; } int now=root; while(1){ tree[now].size++; if(tree[now].val==val){ tree[now].sum++; return now; } int nxt=tree[now].val>val?0:1; if(tree[now].e[nxt]==0){ connect(create(val,now),now,nxt); update(now); return tot; } now=tree[now].e[nxt]; } } void insert(int val){ int p=build(val); if(++CNT=30){ CNT=0; splay(p,root); } } int find(int val){ int now=root; while(now){ if(tree[now].val==val) return now; int nxt=val<tree[now].val?0:1; now=tree[now].e[nxt]; } return 0; } inline void dele(int x){ tree[x].e[1]=tree[x].e[0]=tree[x].fa=0; if(x==tot) tot--; } void pop(int val){ int deal=find(val); if(deal==0) return; splay(deal,root); if(tree[deal].sum>1){ tree[deal].size--; tree[deal].sum--; return; } if(tree[deal].e[0]==0){ root=tree[deal].e[1]; tree[root].fa=0; } else{ int le=tree[deal].e[0]; while(tree[le].e[1]) le=tree[le].e[1]; splay(le,tree[deal].e[0]); connect(tree[deal].e[1],le,1); connect(le,0,1); update(le); root=le; } dele(deal); } int rank(int val){ int now=root,ans=0; while(now){ if(tree[now].val==val) return ans+tree[tree[now].e[0]].size+1; int nxt=val<tree[now].val?0:1; if(nxt==0) now=tree[now].e[0]; else{ ans+=tree[tree[now].e[0]].size+tree[now].sum; now=tree[now].e[1]; } } } inline int arank(){ int now=root; while(tree[now].e[0]) now=tree[now].e[0]; if(++CNT==30){ splay(now,root); CNT=0; } return tree[now].val; } int lower(int val){ int ans=-700000000,now=root; while(now){ if(tree[now].val==val){ splay(now,root); return val; } if(tree[now].val<val&&tree[now].val>ans) ans=tree[now].val; if(tree[now].val>val) now=tree[now].e[0]; else now=tree[now].e[1]; } return ans; } int upper(int val){ int ans=700000000,now=root; while(now){ if(tree[now].val==val) return val; if(tree[now].val>val&&tree[now].val<ans) ans=tree[now].val; if(tree[now].val<val) now=tree[now].e[1]; else now=tree[now].e[0]; } return ans; } }s,d; int q[maxn]; int w[maxn]; int ans=700000000; int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i){ q[i]=w[i]=read(); if(i!=1) s.insert(abs(q[i]-q[i-1])); int now=min(abs(d.lower(q[i])-q[i]),abs(d.upper(q[i])-q[i])); d.insert(q[i]); if(now<ans) ans=now; } for(register int i=1;i<=m;++i){ char ch[20]; scanf("%s",ch); switch(ch[4]){ case 'R':{ int a=read(),b=read(); s.pop(abs(w[a]-q[a+1])); s.insert(abs(w[a]-b)); s.insert(abs(b-q[a+1])); w[a]=b; int now=min(abs(d.lower(b)-b),abs(d.upper(b)-b)); if(now<ans) ans=now; d.insert(b); break; } case 'G':printf("%d\n",s.arank()); break; case 'S':printf("%d\n",ans); break; } } return 0; }