zoukankan      html  css  js  c++  java
  • UVA10107 【What is the Median?】

    题目大意(:)给定一个序列,刚开始序列为空,每次向序列中插入一个数(X),同时维护并输出插入完后序列的中位数为多少。保证(0leq X < 2^{31}),且插入的数的个数(N<10000)

    分析(:)数据范围虽然只有(10000),显然我们可以每次插入完之后暴力(sort),然后输出序列中间的值即可。但这道题的数据范围明显可以增大到(1e5),直接会把暴力的做法卡死。

    所以我们考虑正解(:)平衡树

    平衡树维护中位数时,每次插入完一个数,若当前数的个数为偶数,则查询并输出排名为(n>>1)(n>>1|1)的两个位置的数的平均数;若当前数的个数为奇数,则直接输出排名为(n>>1|1)的位置的数即可。

    至于平衡树的话,有以下几种选择(:)

    • (Treap :) 代码又臭又长,不好写,不好调试,不予考虑

    • (Splay:) 曾经的(flag:)(LCT)前只写(FHQ Treap!!)

    • (FHQ Treap :) 代码简短,思路清晰,常数略大,好写好调试

    具体还有一些细节在代码里会有说明。

    上代码(:)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <ctime>
    
    const int maxn = 1e6 + 5;
    int n, m, w, ch;
    
    template<class T>
    inline T read(T &x) {
        x = 0, w = 1, ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') w = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = getchar();}
        return x *= w;
    } // 来份快读
    
    struct Node {
        int ls, rs, size;
        int key, val;
    }z[maxn];
    int root, cnt;
    int l, r, temp;
    
    void update(int rt) {
        z[rt].size = z[z[rt].ls].size + z[z[rt].rs].size + 1;
    }
    
    int new_node(int x) {
        ++cnt;
        z[cnt].size = 1;
        #ifdef Unix
        z[cnt].key = rand();
        #else
        z[cnt].key = rand() << 15 + rand();
        #endif // Unix
        // Lunix 系统下rand()可以取到INT_MAX,windows系统下只能取到3万多,所以差别处理
        z[cnt].val = x;
        return cnt;
    }
    
    int merge(int x, int y) { // 合并操作
        if (!x || !y) return x + y;
        if (z[x].key < z[y].key) {
            z[x].rs = merge(z[x].rs, y);
            update(x);
            return x;
        }
        else {
            z[y].ls = merge(x, z[y].ls);
            update(y);
            return y;
        }
    }
    
    void split(int rt, int x, int &l, int &r) { // 分离操作
        if (!rt) l = r = 0;
        else {
            if (x < z[rt].val) {
                r = rt;
                split(z[rt].ls, x, l, z[rt].ls);
            }
            else {
                l = rt;
                split(z[rt].rs, x, z[rt].rs, r);
            }
            update(rt);
        }
    }
    
    int rnk(int rt, int x) { //查询排名为x的数的位置
        while(true) {
            if (x <= z[z[rt].ls].size) {
                rt = z[rt].ls;
            }
            else if (z[z[rt].ls].size + 1 == x) return rt;
            else {
                x -= z[z[rt].ls].size + 1;
                rt = z[rt].rs;
            }
        }
    }
    
    int main() {
        srand(time(NULL)); // 随机数……
        while (scanf("%d", &temp) != EOF) {
            split(root, temp, l, r);
            root = merge(merge(l, new_node(temp)), r); // fhq treap 的 insert (基本操作)
            if (cnt & 1) {
                printf("%d
    ", z[rnk(root, (cnt >> 1) + 1)].val);
            }
            else {
                int ans1 = z[rnk(root, cnt >> 1)].val, ans2 = z[rnk(root, (cnt >> 1) + 1)].val;
                printf("%d
    ", (ans1 + ans2) >> 1);
            }
        }
        return 0;
    }
    
    

    完结撒花d=====( ̄▽ ̄*)b

  • 相关阅读:
    jQuery插件之jquery editable plugin点击编辑文字插件
    firefox与ie的javascript兼容性编程汇编【转载】
    css前端制作 经验总结
    非常棒的jqChart图表插件
    WPF Image Source设置文件路径后 在编辑状态下显示图片,运行时不显示
    WPF RadioButton 绑定枚举
    WPF MVVM实现数据增删改查逻辑全流程详细解析demo
    bigNumber.js的简单使用
    PHP程序的“Missing argument 3”的错误提示解决方法
    PHP判断0和空的方法
  • 原文地址:https://www.cnblogs.com/Hydrogen-Helium/p/11738006.html
Copyright © 2011-2022 走看看