BZOJ1208_寵物收養所_KEY
阿新 • • 發佈:2018-03-17
getch using php ++ com target ref AC oot
題目傳送門
平衡樹的題。
因為題目給出條件(其實自己也知道):同一時間呆在收養所中的,要麽全是寵物,要麽全是領養者,這些寵物和領養者的個數不會超過10000個。
所以只要維護一顆平衡樹,它的裏面要不全是人,要不全是寵物。
找到人的前驅後繼比較。
code:
/************************************************************** Problem: 1208 User: yekehe Language: C++ Result: Accepted Time:180 ms Memory:2388 kb ****************************************************************/ #include <cstdio> #include <cstdlib> using namespace std; int read() { char c;while(c=getchar(),c<‘0‘||c>‘9‘); int x=c-‘0‘;while(c=getchar(),c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘; return x; } int N,now,root,cnt,dist; int tr[80005][2],v[80005],r[80005],f[80005];void clear(int x){f[x]=tr[x][0]=tr[x][1]=r[x]=v[x]=0;} void up(int x){f[x]=f[tr[x][0]]+f[tr[x][1]];} int abs(int x){return x>0?x:-x;} void rotate(int &x,int o) { int k=tr[x][o]; tr[x][o]=tr[k][o^1]; tr[k][o^1]=x; f[k]=f[x]; up(x); x=k; } void insert(int &x,intval) { if(!x){ x=++cnt; v[x]=val; r[x]=rand(); f[x]++; return ; } int to=val>v[x]; insert(tr[x][to],val); if(r[x]>r[tr[x][to]])rotate(x,to); return ; } void del(int &x,int val) { if(v[x]==val){ if(!(tr[x][0]+tr[x][1])){ clear(x);x=0; return ; } if(!(tr[x][0]*tr[x][1])){ int w=tr[x][0]+tr[x][1]; clear(x);x=w; return ; } rotate(x,0); del(x,val); return ; } f[x]--; int to=val>v[x]; del(tr[x][to],val); up(x); return ; } void pre(int x,int val)//前驅 { if(!x)return ; if(v[x]>=val)pre(tr[x][0],val); else{ dist=x; pre(tr[x][1],val); } } void bac(int x,int val)//後繼 { if(!x)return ; if(v[x]<=val)bac(tr[x][1],val); else{ dist=x; bac(tr[x][0],val); } } int main() { srand(23333); N=read(); int i,ans=0,o1,o2,tot=0; for(i=1;i<=N;i++){ int x=read(),y=read(); if(!tot){insert(root,y),now=x;tot++;continue;} if(now==x)insert(root,y),tot++; else{ dist=0;pre(root,y);o1=dist; dist=0;bac(root,y);o2=dist; if(!o1&&!o2)continue; int k1=o1?y-v[o1]:2e9,k2=o2?v[o2]-y:2e9; dist=k1>k2?o2:o1;//找較接近的值 ans=(ans+abs(v[dist]-y))%1000000; del(root,v[dist]); tot--; } } printf("%d",ans); return 0; }
BZOJ1208_寵物收養所_KEY