[洛谷P2286][题解][HNOI2004]宠物收养场
0.写在前面
终于靠这道题完成了寒假以来十棵平衡树的flag。。。
特著此题解以纪念
1.思路
可能有人会想到维护两个平衡树,但当你读过题之后就会发现:
人和宠物本质是一样的!!!
所以,写一棵就够了。
其他的都是模板,相信做到这种题的巨佬肯定都会了,不做细讲。
领养/被领养的步骤按题意模拟即可。
2.细节
关于平衡树的选用随便啦~反正我是 Splay
党~
取领养/被领养的家伙的时候要注意取等号!!!
3.代码
缺省源?自己找!
#define N 80010
#define mod 1000000
int n,root,tot,ans;//有人说ans要LL,其实膜好了不需要LL的
int fa[N],ch[N][2];
int data[N],siz[N];
int st;//来人+1,来宠物-1
//-----*平衡树基本操作始*-----//
inline int Son(int k){
return ch[fa[k]][1]==k;
}
inline void Pushup(int k){
siz[k]=siz[ls]+siz[rs]+1;
}
inline void Rotate(int k){
int fk=fa[k],gfk=fa[fk];
int b=Son(k),c=Son(fk),a=ch[k][!b];
ch[gfk][c]=k,fa[k]=gfk;
ch[fk][b]=a,fa[a]=fk;
ch[k][!b]=fk,fa[fk]=k;
Pushup(k),Pushup(fk);
}
inline void Splay(int k,int to=0){
while(fa[k]!=to){
int fk=fa[k],gfk=fa[fk];
if(gfk!=to){
if(Son(k)==Son(fk))Rotate(fk);
else Rotate(k);
}
Rotate(k);
}
if(!to)root=k;
}
inline void Insert(int num){
int k=root,tmp=0;
while(k&&data[k]!=num){
tmp=k,k=ch[k][num>data[k]];
}
if(!k){
k=++tot;
if(tmp)ch[tmp][num>data[tmp]]=k;
fa[k]=tmp,data[k]=num;
ls=rs=0;
}
Splay(k);
}
inline void Find(int num){
int k=root;
while(data[k]!=num&&ch[k][num>data[k]]){
k=ch[k][num>data[k]];
}
Splay(k);
}
inline int Get(int num,int opt){
Find(num);
int k=root;
if(opt&&num<data[k])return k;
if(!opt&&num>data[k])return k;
k=ch[k][opt];
while(ch[k][opt^1])k=ch[k][opt^1];
return k;
}
inline int Gete(int num,int opt){
Find(num);
int k=root;
if(opt&&num<=data[k])return k;
if(!opt&&num>=data[k])return k;
k=ch[k][opt];
while(ch[k][opt^1])k=ch[k][opt^1];
return k;
}
inline void Delete(int num){
int l=Get(num,0),r=Get(num,1);
Splay(l),Splay(r,l);
ch[r][0]=0;
}
//-----*平衡树基本操作完*-----//
int main(){
Insert(-INF),Insert(INF);//防爆基本操作
Read(n);
for(rg int i=1;i<=n;i++){
int opt,num;
Read(opt),Read(num);
if(st==0)Insert(num);//空了
else if(st<0){//全是宠物
if(opt==1)Insert(num);
else {
int pred=data[Gete(num,0)];
int sufd=data[Gete(num,1)];
if(abs(pred-num)<=abs(sufd-num)){
ans=(ans+abs(pred-num))%mod;
Delete(pred);
}else {
ans=(ans+abs(sufd-num))%mod;
Delete(sufd);
}
}
}else {//全是人
if(opt==0)Insert(num);
else {
int pred=data[Gete(num,0)];
int sufd=data[Gete(num,1)];
if(abs(pred-num)<=abs(sufd-num)){
ans=(ans+abs(pred-num))%mod;
Delete(pred);
}else {
ans=(ans+abs(sufd-num))%mod;
Delete(sufd);
}
}
}
st+=(opt==0)?1:-1;
}
cout<<ans<<endl;
return 0;
}
4.完结撒花
内容来自_ajthreac_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。