HNOI2004 宠物收养所 splay
看清楚题意后居然一A了,这么长的代码一A对我来说还真是少见。
突然弄懂了数组版splay的内存池的原理,还是很简单的。。。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; const int MOD=1000000; int n; int op,x; struct Splay { ll key[maxn]; int pre[maxn],ch[maxn][2],rt,tot1; int s[maxn],tot2; void newnode(int &r,int fa,ll k) { if(tot2) r=s[tot2--]; else r=++tot1; key[r]=k;pre[r]=fa; MS0(ch[r]); } void rot(int x,int kind) { int y=pre[x]; ch[y][kind^1]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; } void splay(int x,int goal) { while(pre[x]!=goal){ if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x); else{ int y=pre[x],z=pre[y]; int kind=ch[y][0]==x,one=0; if(ch[y][0]==x&&ch[z][0]==y) one=1; if(ch[y][1]==x&&ch[z][1]==y) one=1; if(one) rot(y,kind),rot(x,kind); else rot(x,kind),rot(x,kind^1); } } if(goal==0) rt=x; } void Del() { if(!ch[rt][0]&&!ch[rt][1]) rt=0,tot1=tot2=0; else if(!ch[rt][0]) s[++tot2]=rt,rt=ch[rt][1],pre[rt]=0; else if(!ch[rt][1]) s[++tot2]=rt,rt=ch[rt][0],pre[rt]=0; else{ int r=ch[rt][0]; while(ch[r][1]) r=ch[r][1]; splay(r,rt); s[++tot2]=rt; ch[r][1]=ch[rt][1]; pre[ch[r][1]]=r; rt=r; pre[rt]=0; } } int Find(ll k) { if(rt==0) return 0; int r=rt,f=0; while(r){ if(key[r]==k){ splay(r,0); return 1; } f=r; r=ch[r][k>key[r]]; } splay(f,0); return 0; } void Insert(ll x) { if(rt==0) newnode(rt,0,x); else{ int r=rt,f=0; while(r){ if(key[r]==x){ splay(r,0); return; } f=r;r=ch[r][x>key[r]]; } newnode(ch[f][x>key[f]],f,x); splay(ch[f][x>key[f]],0); } } void init() { rt=tot1=0; tot2=0; MS0(pre);MS0(key);MS0(ch); } ll get_pre(int x) { if(!ch[x][0]) return -1; x=ch[x][0]; while(ch[x][1]) x=ch[x][1]; return key[x]; } ll get_next(int x) { if(!ch[x][1]) return -1; x=ch[x][1]; while(ch[x][0]) x=ch[x][0]; return key[x]; } };Splay A,P; int main() { freopen("in.txt","r",stdin); while(cin>>n){ A.init();P.init(); ll ans=0; REP(i,1,n){ scanf("%d%d",&op,&x); if(op==0){ if(P.rt!=0){ if(P.Find(x)) P.Del(); else{ int y=P.key[P.rt],z; if(x<y){ z=P.get_pre(P.rt); if(z!=-1&&abs(x-z)<=abs(x-y)) P.Find(z); P.Del(); } else{ z=P.get_next(P.rt); if(z!=-1&&abs(x-y)>abs(x-z)) P.Find(z); P.Del(); } if(z!=-1) ans+=min(abs(x-z),abs(x-y)); else ans+=abs(x-y); //cout<<"x="<<x<<" y="<<y<<" z="<<z<<endl; ans%=MOD; } } else A.Insert(x); } else{ if(A.rt!=0){ if(A.Find(x)) A.Del(); else{ ll y=A.key[A.rt],z; if(x<y){ z=A.get_pre(A.rt); if(z!=-1&&abs(x-z)<=abs(x-y)) A.Find(z); A.Del(); } else{ z=A.get_next(A.rt); if(z!=-1&&abs(x-y)>abs(x-z)) A.Find(z); A.Del(); } if(z!=-1) ans+=min(abs(x-z),abs(x-y)); else ans+=abs(x-y); //cout<<"x="<<x<<" y="<<y<<" z="<<z<<endl; ans%=MOD; } } else P.Insert(x); } } cout<<ans%MOD<<endl; } return 0; }
没有AC不了的题,只有不努力的ACMER!