UVa1402/LA3961 Robotic Sort

题目链接

         本题是2007年ICPC欧洲区域赛中欧赛区S

题意

        一个实验室里有 n 个长短不一的试管。你的任务是编写一段程序,用机器臂把它们按照高度从小到大的顺序排列。对于高度相同的试管,排序前后的相对位置应保持不变。排序方法如下图所示。

        排序需要n 次操作,其中第i 次操作是“反转”序列i~Pi,其中Pi是目标状态中第i个试管当前所在的位置。比如,在上图中,初始时P1=4,因此反转试管1~4 就能把最左边的试管归位。类似地,第2 次操作前P2=6,因此反转试管2~6 就能把左数第2 个试管归位。
        你的任务是输出 P1, P2, …, Pn 的值,以便控制机器臂移动。注意i=Pi时实际上不需要反转,但仍然需要输出Pi。

分析

        伸展树(splay)模板题,用懒标记表示反转提升效率,需要解决的一个难点:求特定结点的排名。给伸展树结点添加父指针字段,借助父指针可实现单次求特定结点排名的O(logn)时间复杂度算法。

        说一个用伸展树解题时缩短运行时间的技巧:初始化时将伸展树构建成平衡二叉树。

AC代码

#include <iostream>
#include <algorithm>
using namespace std;

#define N 100050
int h[N], a[N] = {0}, c[N], n;
struct node {
    node *ch[2] = {NULL, NULL}, *fa = NULL; int s = 0, flip = 0;
    int cmp(int k) const {
        int d = k - ch[0]->s;
        return d == 1 ? -1 : d > 0;
    }
    void maintain() {
        s = ch[0]->s + ch[1]->s + 1;
    }
    void pushdown() {
        if (flip) {
            flip = 0;
            node *p = ch[0]; ch[0] = ch[1]; ch[1] = p;
            ch[0]->flip ^= 1; ch[1]->flip ^= 1;
        }
    }
} *null = new node(), *q[N], s[N];

node* rotate(node* o, int d) {
    node* k = o->ch[d^1];
    o->ch[d^1] = k->ch[d];
    k->ch[d]->fa = o;
    k->ch[d] = o;
    if (o->fa) o->fa->ch[o->fa->ch[1] == o] = k;
    k->fa = o->fa;
    o->fa = k;
    o->maintain();
    k->maintain();
    return k;
}

void splay(node*& o, int k) {
    o->pushdown();
    int d = o->cmp(k);
    if (d == -1) return;
    if (d) k -= o->ch[0]->s + 1;
    node* p = o->ch[d];
    p->pushdown();
    int d2 = p->cmp(k);
    if (d2 != -1) {
        splay(p->ch[d2], d2 ? k - p->ch[0]->s - 1 : k);
        if (d == d2) o = rotate(o, d^1);
        else o->ch[d] = rotate(o->ch[d], d);
    }
    o = rotate(o, d^1);
}

node* merge(node* left, node* right) {
    splay(left, left->s);
    left->ch[1] = right;
    right->fa = left;
    left->maintain();
    return left;
}

void split(node* o, int k, node*& left, node*& right) {
    splay(o, k);
    left = o;
    right = o->ch[1];
    right->fa = NULL;
    o->ch[1] = null;
    left->maintain();
}

int rnk(node* o) {
    int s = 0, t = 1; q[0] = o;
    while (o->fa) o = o->fa, q[t++] = o;
    while (t--) {
        q[t]->pushdown();
        if (!t || q[t-1] == q[t]->ch[1]) s += q[t]->ch[0]->s + 1;
    }
    return s;
}

node* build(int x, int l, int r) {
    node* o = q[x];
    o->ch[0] = l>1 ? build(x-1-(l-1>>1), l-1-(l-1>>1), l-1>>1) : null; o->ch[0]->fa = o;
    o->ch[1] = r ? build(x+r-(r>>1), r-(r>>1), r>>1) : null; o->ch[1]->fa = o;
    o->s = l+r; o->flip = 0; o->fa = NULL;
    return o;
}

void solve() {
    for (int i=1; i<=n; ++i) cin >> h[i], a[i] = h[i], c[i] = 0;
    sort(a+1, a+n+1);
    for (int i=1, j; i<=n; ++i) j = lower_bound(a, a+n+1, h[i]) - a, q[i] = s + j + c[j]++;
    node *root = build(n-(n>>1), n-(n>>1), n>>1), *o, *l, *r, *mid;
    for (int i=1; i<n; ++i) {
        int j = rnk(s+i);
        cout << j << ' ';
        if (j > i) {
            split(root, j, o, r);
            if (i > 1) {
                split(o, i-1, l, mid);
                mid -> flip ^= 1;
                root = merge(merge(l, mid), r);
            } else o -> flip ^= 1, root = merge(o, r);
        }
    }
    cout << n << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while (cin>>n && n) solve();
    return 0;
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
04-26
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值