zoukankan      html  css  js  c++  java
  • P4402 [Cerc2007]robotic sort 机械排序 题解

    Description

    Luogu传送门

    Solution

    题目要求我们找到第 \(i\) 的数,其实就维护一下剩下的数中最小值在哪里即可。

    我们考虑使用 \(fhq-treap\)

    说一下具体实现过程:

    • 找到剩下的点中的最小值(其实就是根)。
    • 输出答案,删去它,合并它的两个儿子。
    • 维护区间翻转标记并下传。

    然后就没了。。甚至连 split 都不需要(

    并且维护的这个最小值正好满足小根堆的性质,为了方便,我们可以拿输入的数代替 rand 的值。

    (但是会被卡)

    我们考虑优化建树,使用建笛卡尔树的思想来建树。

    关于笛卡尔树,戳这里

    我们把权值小于当前权值的点挂到当前点的左子树上,再把当前点挂到第一个大于它的点的右子树上,即可构建出一棵相对平衡的平衡树(事实上跑的飞快)。

    这个过程就用单调栈维护一下即可。

    (这样一来反而不如普通的 \(fhq-treap\) 好写了 QwQ)

    还有无关紧要的一点,题目中可能会输入相同的数,如有相同先输出最靠左的,所以稍微处理一下即可,具体见代码。

    Code

    #include <bits/stdc++.h>
    #define ll long long
    #define ls(x) t[x].l
    #define rs(x) t[x].r
    
    using namespace std;
    
    namespace IO{
        inline int read(){
            int x = 0;
            char ch = getchar();
            while(!isdigit(ch)) ch = getchar();
            while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
            return x;
        }
    
        template <typename T> inline void write(T x){
            if(x > 9) write(x / 10);
            putchar(x % 10 + '0');
        }
    }
    using namespace IO;
    
    const int N = 1e5 + 10;
    int n;
    struct fhq_treap{
        int siz, val, l, r;
        ll wei;
        bool rev;
    }t[N];
    int rt, tot;
    
    inline void pushup(int x){
        t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
    }
    
    inline void pushdown(int x){
        if(t[x].rev){
            swap(ls(x), rs(x));
            if(ls(x)) t[ls(x)].rev ^= 1;
            if(rs(x)) t[rs(x)].rev ^= 1;
            t[x].rev = 0;
        }
    }
    
    inline int merge(int x, int y){
        if(!x || !y) return x | y;
        if(t[x].wei <= t[y].wei){
            pushdown(x);
            rs(x) = merge(rs(x), y);
            return pushup(x), x;
        }else{
            pushdown(y);
            ls(y) = merge(x, ls(y));
            return pushup(y), y;
        }
    }
    
    int stk[N], top;
    
    inline void build(int x){
        while(top && t[x].wei < t[stk[top]].wei) ls(x) = stk[top--], pushup(ls(x));
        if(top) rs(stk[top]) = x;
        stk[++top] = x;
    }
    
    inline void update(int x){
        int l = ls(x), r = rs(x);
        ls(x) = rs(x) = 0;
        t[l].rev ^= 1;
        rt = merge(l, r);
    }
    
    signed main(){
        n = read();
        for(int i = 1; i <= n; ++i){
            t[i].wei = 1ll * read() * n + i, t[i].val = i, t[i].siz = 1;
            build(i);
        }
        while(top) pushup(stk[top--]);
        rt = stk[1];
        for(int i = 1; i <= n; ++i){
            pushdown(rt);
            write(t[ls(rt)].siz + i), putchar(' ');
            update(rt);
        }
        return puts(""), 0;
    }
    

    \[\_EOF\_ \]

  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/xixike/p/15726570.html
Copyright © 2011-2022 走看看