【题解】Luogu P2073 送花

原题传送门

这题需要用到Splay

我们用一棵splay维护金钱

考虑c<=1000000

我们珂以把每种价格现在对应的美丽值存在一个a数组中

这样讲有珂能不太清楚qaq,还是对着操作一个一个讲

操作一:

先在这棵splay中查找是否有这种花的金钱

如果有,直接跳过

如果没有,a[c]=m,把金钱为c的花的美丽值存下,把两个所求答案更新,把c插入平衡树

操作2,3:

执行所有操作之前先把inf,-inf插入平衡树

删除最小就是删除-inf的后继,删除最大就是删除inf的前驱

但还要加上特判,在后继(前驱)不等于inf(-inf)的情况下,更新答案,a数组变成0,把该节点从平衡树中删除

完整代码

#include <bits/stdc++.h>
#define inf 1000000005
#define N 100005
#define root tree[0].ch[1]
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=nc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
struct Splay{
    int v,fa,ch[2],sum;
}tree[N];
int tot;
inline bool findd(register int x)
{
    return x==tree[tree[x].fa].ch[0]?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
    tree[x].fa=fa;
    tree[fa].ch[son]=x;
}
inline void update(register int x)
{
    tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+1;
}
inline void rotate(register int x)
{
    int Y=tree[x].fa;
    int R=tree[Y].fa;
    int Yson=findd(x);
    int Rson=findd(Y);
    int B=tree[x].ch[Yson^1];
    connect(B,Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    update(Y),update(x);
}
inline void splay(register int x,register int to)
{
    to=tree[to].fa;
    while(tree[x].fa!=to)
    {
        int y=tree[x].fa;
        if(tree[y].fa==to)
            rotate(x);
        else if(findd(x)==findd(y))
            rotate(y),rotate(x);
        else
            rotate(x),rotate(x);
    }
}
inline int newpoint(register int v,register int fa)
{
    tree[++tot].fa=fa;
    tree[tot].v=v;
    tree[tot].sum=1;
    return tot;
}
inline void Insert(register int x)
{
    int now=root;
    if(root==0)
    {
        newpoint(x,0);
        root=tot;
    }
    else
    {
        while(19260817)
        {
            ++tree[now].sum;
            int nxt=x<tree[now].v?0:1;
            if(!tree[now].ch[nxt])
            {
                int p=newpoint(x,now);
                tree[now].ch[nxt]=p;
                splay(p,root);
                return;
            }
            now=tree[now].ch[nxt];
        }
    }
}
inline int find(register int v)
{
    int now=root;
    while(19260817)
    {
        if(tree[now].v==v)
        {
            splay(now,root);
            return now;
        }
        int nxt=v<tree[now].v?0:1;
        if(!tree[now].ch[nxt])
            return 0;
        now=tree[now].ch[nxt];
    }
}
inline void delet(register int x)
{
    int pos=find(x);
    if(!pos)
        return;
    if(!tree[pos].ch[0]&&!tree[pos].ch[1])
        root=0;
    else if(!tree[pos].ch[0])
    {
        root=tree[pos].ch[1];
        tree[root].fa=0;
    }
    else
    {
        int left=tree[pos].ch[0];
        while(tree[left].ch[1])
            left=tree[left].ch[1];
        splay(left,tree[pos].ch[0]);
        connect(tree[pos].ch[1],left,1);
        connect(left,0,1);
        update(left);
    }
}
inline int lower(register int v)
{
    int now=root;
    int ans=-inf;
    while(now)
    {
        if(tree[now].v<v&&tree[now].v>ans)
            ans=tree[now].v;
        if(v>tree[now].v)
            now=tree[now].ch[1];
        else
            now=tree[now].ch[0];
    }
    return ans;
}
inline int upper(register int v)
{
    int now=root;
    int ans=inf;
    while(now)
    {
        if(tree[now].v>v&&tree[now].v<ans)
            ans=tree[now].v;
        if(v<tree[now].v)
            now=tree[now].ch[0];
        else
            now=tree[now].ch[1];
    }
    return ans;
}
int a[1000005];
int main()
{
    Insert(inf);
    Insert(-inf);
    int opt=read(),ans1=0,ans2=0;
    while(opt!=-1)
    {
        if(opt==1)
        {
            int w=read(),c=read();
            if(!find(c))
            {
                ans1+=w,ans2+=c;
                a[c]=w;
                Insert(c);
            }
        }
        else if(opt==2)
        {
            int c=lower(inf);
            if(c!=-inf)
            {
                ans1-=a[c],ans2-=c;
                a[c]=0;
                delet(c);
            }
        }
        else
        {
            int c=upper(-inf);
            if(c!=inf)
            {
                ans1-=a[c],ans2-=c;
                a[c]=0;
                delet(c);
            }
        }
        opt=read();
    }
    write(ans1),putchar(' '),write(ans2);
    return 0;
 } 

猜你喜欢

转载自www.cnblogs.com/yzhang-rp-inf/p/10017405.html