BZOJ 1208 [HNOI2004]宠物收养所 | SPlay模板题

题目:

洛谷也能评


题解:

记录一下当前树维护是宠物还是人,用Splay维护插入和删除.

对于任何一次询问操作都求一下value的前驱和后继(这里前驱和后继是可以和value相等的),比较哪个差值绝对值小就好啦

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 800010
#define MOD 1000000
#define which(x) (ls[fa[(x)]]==(x))
typedef long long ll;
using namespace std;
int n,root,tot,val[N],fa[N],ls[N],rs[N],sze[N],cnt[N],flag,op,value;
ll ans;
int read()
{
    int ret=0,neg=1;
    char j=getchar();
    for (;j>'9' || j<'0';j=getchar())
    if (j=='-') neg=-1;
    for (;j>='0' && j<='9';j=getchar())
    ret=ret*10+j-'0';
    return ret*neg;
}
void Upt(int x) {sze[x]=sze[ls[x]]+sze[rs[x]]+1;}
void Rotate(int u)
{
    int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
    if (w) which(v)?ls[w]=u:rs[w]=u;
    which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
    fa[u]=w,fa[v]=u;
    if (b) fa[b]=v;
    Upt(v),Upt(u);
}
void Splay(int x)
{
    while (fa[x])
    {
    if (fa[fa[x]])
        if (which(x)==which(fa[x])) Rotate(fa[x]);
        else Rotate(x);
    Rotate(x);
    }
    root=x;
}
void Insert(int x)
{
    int cur=root,v=0;
    while (cur)
    if (x<val[v=cur]) cur=ls[cur];
    else cur=rs[cur];
    fa[++tot]=v,val[tot]=x,sze[tot]=1;
    if (v) x<val[v]?ls[v]=tot:rs[v]=tot;
    Splay(tot);
}
int Find(int x)
{
    int cur=root,v=0;
    while (cur && val[cur]!=x)
    if (x<val[v=cur]) cur=ls[cur];
    else cur=rs[cur];
    return cur?cur:v;
}
int getmin(int x)
{
    while (ls[x]) x=ls[x];
    return x;
}
int getmax(int x)
{
    while (rs[x]) x=rs[x];
    return x;
}
int getpre(int x)
{
    int u=Find(x);
    Splay(u);
    if (val[u]<=x) return u;
    return getmax(ls[u]);
}
int getnxt(int x)
{
    int u=Find(x);
    Splay(u);
    if (val[u]>=x) return u;
    return getmin(rs[u]);
}
void Erase(int x)
{
    Splay(x);
    if (ls[x]==0 && rs[x]==0) root=0;
    else
    if (ls[x]==0 || rs[x]==0) root=ls[x]+rs[x],fa[root]=0;
    else{
        
        fa[ls[x]]=0;
        int v=getmax(ls[x]);
        Splay(v);
        rs[v]=rs[x],fa[rs[x]]=v,Upt(root);
    }
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
    op=read(),value=read();
    if (sze[root]==0)
       Insert(value),flag=op;
    else if (op!=flag)
    {
        int u=getpre(value),v=getnxt(value);
        if (u!=0 && (v==0 || value-val[u]<=val[v]-value))
        ans=(ans+value-val[u])%MOD,Erase(u);
        else ans=(ans+val[v]-value)%MOD,Erase(v);
    }
    else Insert(value);
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/mrsheep/p/8118447.html