BZOJ 4825: [AH2017/HNOI2017]单旋 LCT set

title

BZOJ 4825

LUOGU 3721

题面巨长,不想贴了,不然这篇 \(blog\) 就都成题面了

analysis

\(Orz\) yyb

这题的题目让你维护一个 \(splay\) ,正解就肯定不是 \(splay\) 了,要不然就有点不正常了(刚才去翻了一下洛谷题解,好像真的有大佬是写了 \(splay\) 的,有点打脸)。

反正我选择用 \(LCT\) 来维护这棵 \(splay\) 了(默认 \(LCT\) 都会写了)。

下面说下五个操作:

  1. 第一个操作,一个新建入的节点要么接在前驱的右儿子,要么接在后继的左儿子,那么,搞一个 \(set\) 求一求前驱后继,很容易证明前驱的右儿子和后继的左儿子一定有且仅有一个为空,直接接上去就行了。

  2. 剩下的四个操作,最大/最小值旋到根,就是把它的儿子给父亲,然后 \(root\) 直接变成它的儿子,它变成 \(root\) ,于是每次的操作之和两个点有关,在 \(LCT\) 中维护点在 \(spaly\) 上的父子关系。(在删除操作的时候,要先判断这个点已经是 \(root\) 的情况的)

code

写的巨长,\(258\)

#include<bits/stdc++.h>

const int maxn=2e5+10;

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

namespace LCT
{
    int ch[maxn][2];
    typedef int iarr[maxn];
    iarr fa,siz,Stack;
    bool r[maxn];
    inline bool nroot(int x)
    {
        return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
    }

    inline void pushup(int x)
    {
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }

    inline void rever(int x)
    {
        std::swap(ch[x][0],ch[x][1]);
        r[x]^=1;
    }

    inline void pushdown(int x)
    {
        if (r[x])
        {
            if (ch[x][0]) rever(ch[x][0]);
            if (ch[x][1]) rever(ch[x][1]);
            r[x]=0;
        }
    }

    inline void rotate(int x)//一次旋转
    {
        int y=fa[x],z=fa[y],k=ch[y][1]==x,w=ch[x][!k];
        if (nroot(y)) ch[z][ch[z][1]==y]=x;
        ch[x][!k]=y,ch[y][k]=w;//额外注意if(nroot(y))语句,此处不判断会引起致命错误(与普通Splay的区别2)
        if (w) fa[w]=y;
        fa[y]=x,fa[x]=z;
        pushup(y);
    }

    inline void splay(int x)
    {
        int y=x,z=0;
        Stack[++z]=y;
        while (nroot(y)) Stack[++z]=y=fa[y];
        while (z) pushdown(Stack[z--]);
        while (nroot(x))
        {
            y=fa[x], z=fa[y];
            if (nroot(y)) rotate((ch[y][0]==x)^(ch[z][0]==y) ? x : y);
            rotate(x);
        }
        pushup(x);
    }

    inline void access(int x)
    {
        for (int y=0; x; y=x, x=fa[x]) splay(x), ch[x][1]=y, pushup(x);
    }

    inline void makeroot(int x)
    {
        access(x);splay(x);rever(x);
    }

    inline int findroot(int x)
    {
        access(x);splay(x);
        while (ch[x][0]) pushdown(x), x=ch[x][0];
        splay(x);
        return x;
    }

    inline void split(int x,int y)
    {
        makeroot(x);
        access(y), splay(y);
    }

    inline void link(int x,int y)
    {
        makeroot(x);
        if (findroot(y)^x) fa[x]=y;
    }

    inline void cut(int x,int y)
    {
        makeroot(x);
        if (findroot(y)==x && fa[y]==x && !ch[y][0])
        {
            fa[y]=ch[x][1]=0;
            pushup(x);
        }
    }
}

using LCT::siz;
using LCT::split;
using LCT::link;
using LCT::cut;

int tot,root;
int ls[maxn],rs[maxn],fa[maxn];
std::map<int,int>M;
std::set<int>s;
inline void insert(int x)
{
    int now=++tot;
    M[x]=now;
    if (s.empty())
    {
        s.insert(x);
        root=now;
        write(1,'\n');
        return ;
    }
    std::set<int>::iterator it=s.upper_bound(x);
    if (it==s.end() || ls[M[*it]])
    {
        --it;
        int k=M[*it];
        link(now,k), rs[k]=now, fa[now]=k;
    }
    else
    {
        int k=M[*it];
        link(now,k), ls[k]=now,fa[now]=k;
    }
    s.insert(x);
    split(now,root);
    write(siz[root],'\n');
}

inline void Splay_min()
{
    int x=M[*s.begin()];
    if (root==x) { write(1,'\n'); return ; }
    split(x,root);
    write(siz[root],'\n');
    cut(x,fa[x]);
    if (rs[x]) cut(x,rs[x]);
    link(x,root);
    if (rs[x]) link(fa[x],rs[x]);
    ls[fa[x]]=rs[x];
    if (rs[x]) fa[rs[x]]=fa[x];
    fa[x]=0, fa[root]=x, rs[x]=root;
    root=x;
}

inline void Splay_max()
{
    int x=M[*--s.end()];
    if (root==x) { write(1,'\n'); return ; }
    split(x,root);
    write(siz[root],'\n');
    cut(x,fa[x]);
    if (ls[x]) cut(x,ls[x]);
    link(x,root);
    if (ls[x]) link(ls[x],fa[x]);
    rs[fa[x]]=ls[x];
    if (ls[x]) fa[ls[x]]=fa[x];
    fa[x]=0, fa[root]=x, ls[x]=root;
    root=x;
}

inline void Del_min()
{
    int x=M[*s.begin()];
    if (root==x)
    {
        write(1,'\n');
        if (rs[x]) cut(x,rs[x]);
        fa[rs[x]]=0, root=rs[x];
        s.erase(s.begin());
        return ;
    }
    split(x,root);
    write(siz[root],'\n');
    cut(x,fa[x]);
    if (rs[x]) cut(x,rs[x]);
    if (rs[x]) link(fa[x],rs[x]);
    ls[fa[x]]=rs[x];
    if (rs[x]) fa[rs[x]]=fa[x];
    s.erase(s.begin());
}

inline void Del_max()
{
    int x=M[*--s.end()];
    if (root==x)
    {
        write(1,'\n');
        if (ls[x]) cut(x,ls[x]);
        fa[ls[x]]=0, root=ls[x];
        s.erase(--s.end());
        return ;
    }
    split(x,root);
    write(siz[root],'\n');
    cut(x,fa[x]);
    if (ls[x]) cut(x,ls[x]);
    if (ls[x]) link(ls[x],fa[x]);
    rs[fa[x]]=ls[x];
    if (ls[x]) fa[ls[x]]=fa[x];
    s.erase(--s.end());
}

int main()
{
    int n;read(n);
    while (n--)
    {
        int opt,x;read(opt);
        if (opt==1) read(x), insert(x);
        else if (opt==2) Splay_min();
        else if (opt==3) Splay_max();
        else if (opt==4) Del_min();
        else Del_max();
    }
    IO::flush();
    return 0;
}

转载于:https://www.cnblogs.com/G-hsm/p/11447867.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值