标签:
http://www.lydsy.com/JudgeOnline/problem.php?id=1208
(据说codevs要更新?就不放codevs的地址了吧...)
有宠物和人,每个单位都有一个与其他单位不同的值(正),如果现在有宠物,来了一个人,人取走和他的值最接近的宠物(如果有两个选值小的),如果现在有人,来了一个宠物,和它值最接近的人(如果有两个选值小的)取走它.求每次带宠物走两个单位的值的差的绝对值的总和.
用平衡树查找前驱和后驱即可.依照题意,要么全是人要么全是宠物,所以建一棵树即可.模板题.
注意:
1.判断是否有前驱或后驱时要小心.
p.s.第一道用Splay写的题,调了好久...指针理解的不是很好啊.
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int oo=~0u>>1; struct Treap{ struct node{ node* ch[2]; int v,r,s; node(int v,node* t):v(v){ ch[0]=ch[1]=t; r=rand(); s=1; } void push_up(){ s=ch[0]->s+ch[1]->s+1; } }*root,*null; Treap(){ null=new node(0,NULL); null->s=0; null->r=oo; root=null; } void rot(node* &o,bool d){ node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o; o->push_up(); k->push_up(); o=k; } void insert(node* &o,int x){ if(o==null) o=new node(x,null); else{ bool d=x>o->v; insert(o->ch[d],x); if(o->ch[d]->r<o->r) rot(o,!d); o->push_up(); } } void remove(node* &o,int x){ if(o->v==x){ if(o->ch[0]!=null&&o->ch[1]!=null){ bool d=o->ch[0]->r<o->ch[1]->r; rot(o,d); remove(o->ch[d],x); o->push_up(); } else{ node* u=o; if(o->ch[0]==null) o=o->ch[1]; else o=o->ch[0]; delete u; } } else{ bool d=x>o->v; remove(o->ch[d],x); o->push_up(); } } int pre(int x){ node* t=root; int ret=-1; while(t!=null){ if(t->v<x) ret=t->v,t=t->ch[1]; else t=t->ch[0]; } return ret; } int suc(int x){ node* t=root; int ret=-1; while(t!=null){ if(t->v>x) ret=t->v,t=t->ch[0]; else t=t->ch[1]; } return ret; } }tree; const int maxn=80000+5,mod=1e6; int n; int main(){ scanf("%d",&n); int cnt=0,now,ans=0; while(n--){ int a,b; scanf("%d%d",&a,&b); if(cnt==0) now=a; if(a==now){ tree.insert(tree.root,b); cnt++; } else{ int pre=tree.pre(b); int suc=tree.suc(b); if(pre==-1){ int t=suc-b; ans=(ans+t)%mod; tree.remove(tree.root,suc); } else if(suc==-1){ int t=b-pre; ans=(ans+t)%mod; tree.remove(tree.root,pre); } else{ int t1=b-pre,t2=suc-b; if(t1<=t2){ ans=(ans+t1)%mod; tree.remove(tree.root,pre); } else{ ans=(ans+t2)%mod; tree.remove(tree.root,suc); } } cnt--; } } printf("%d\n",ans); return 0; }
#include <cstdio> #include <algorithm> using namespace std; struct Splay{ struct node{ node* ch[2],*pa; int v; node(int v,node* t):v(v){ ch[0]=ch[1]=pa=t; } bool d(){ return pa->ch[1]==this; } void setc(node* t,bool d) { ch[d]=t; t->pa=this; } }*root,*null; Splay(){ null=new node(0,NULL); root=null; } void rot(node* o){ node* pa=o->pa; bool d=o->d(); pa->pa->setc(o,pa->d()); pa->setc(o->ch[!d],d); o->setc(pa,!d); if(pa==root) root=o; } void splay(node* o,node* pa){ while(o->pa!=pa){ if(o->pa->pa==pa) rot(o); else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o)); } } void insert(int x){ if(root==null){ root=new node(x,null); return; } node* t=root; while(t->ch[x>t->v]!=null&&t->ch[x>t->v]->v!=x) t=t->ch[x>t->v]; if(t->ch[x>t->v]!=null) return; node* k=new node(x,null); t->setc(k,x>t->v); splay(k,null); } int pre(int x){ node* t=root; int ret=-1; while(t!=null){ if(t->v<=x) ret=t->v,t=t->ch[1]; else t=t->ch[0]; } return ret; } int suc(int x){ node* t=root; int ret=-1; while(t!=null){ if(t->v>=x) ret=t->v,t=t->ch[0]; else t=t->ch[1]; } return ret; } }tree; int n,a,ans; int main(){ scanf("%d",&n); scanf("%d",&a); ans+=a; tree.insert(a); n--; while(n--){ scanf("%d",&a); int pre=tree.pre(a); int suc=tree.suc(a); if(pre==-1) ans+=suc-a; else if(suc==-1) ans+=a-pre; else ans+=min(suc-a,a-pre); tree.insert(a); } printf("%d\n",ans); return 0; }
BZOJ_1208Codevs_1258_[HNOI2004]_宠物收养所(Treap/Splay)
标签:
原文地址:http://www.cnblogs.com/Sunnie69/p/5490334.html