zoukankan      html  css  js  c++  java
  • luogu P1168 中位数

    窒息

    这道题令我头秃

    问了问学长思路

    学长如是说:

    “这道题有很多种解题方法,但是你想用线段树对吧

    可以用平衡树来解决,但是你不会,还有主席树,你也不会,

    我又想到了一种需要离散化的线段树做法……”

    所以说那么多我不会的干什么啊!

    这道题我看了很多题解都没看懂

    大概是因为用线段树做有一个数组num记录的是什么没有理解

    那思路嘛

    求中位数

    首先开一个线段树,每当出现一个数时,便把那个数所在的数组加一,表示出现次数

    当你找中位数的时候,从根开始,分别看左子树和右子树的区间和

    如果要找的中位数的位置,即编号x,小于左子树的区间和l

    那么该中位数就在左子树中

    反之,则在右子树的x - l位置上

    emmmm哇还是画图比较好

    然而我没有画图软件所以请自己画一画体验一下

    看一下代码吧

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 100010
    
    struct TREE {
        int l,r,num;
    } tree[maxn << 2];//开四倍啊我一开始忘了wa了两个点
    
    int a[maxn],b[maxn];//a是原数组,b是排序去重后的
    
    void build(int l,int r,int now) {
        tree[now].l = l;
        tree[now].r = r;
        int mid = (l + r) >> 1;
        if(l == r)
            return ;
        build(l,mid,now << 1);
        build(mid + 1,r,now << 1 | 1);
    }//建树的处理
    
    void update(int now,int k) {//当一个位置上有数的时候更新一下,num++
        ++tree[now].num;
        if(tree[now].l == tree[now].r)
            return ;
        int mid = (tree[now].l + tree[now].r) >> 1;
        if(k <= mid)
            update(now << 1,k);
        else
            update(now << 1 | 1,k);
    }
    
    int query(int now,int x) {
        if(tree[now].l == tree[now].r)
            return tree[now].l;
        if(x <= tree[now << 1].num)//如果小于左子树区间和,则中位数在左子树中
            return query(now << 1,x);
        else//反之在右子树里,这是x在右子树中的位置是x - num
            return query(now << 1 | 1,x - tree[now << 1].num);
    }
    
    int main() {
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort(b + 1,b + n + 1);
        int k = unique(b + 1,b + n + 1) - b;//将b排序去重
        build(1,n,1);
    //    for(int i = 1;i < k;i++)
    //    printf("qwq %d ",b[i]);
    //    printf("
    ");
        for(int i = 1; i <= n; i++) {
            int www = lower_bound(b + 1,b + k + 1,a[i]) - b;//求出每次插入的数的位置
        //    printf("qwq %d   %d qwq
    ",a[i],www);
            update(1,www);
            if(i % 2)
                printf("%d
    ",b[query(1,i / 2 + 1)]);//输出中位数所在位置上的数
        }
        return 0;
    }

    大概还比较详细吧www

    最后说一下,ljq学长穿了一件帅气的新衬衫哈哈哈哈哈wxsl

    ————————————————————几分钟的分割线————————————————————————

    阿对

    还有一种短一点的写法

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 100010
    
    struct QAQ {
        int data,num;
    } a[maxn];
    
    int sum[maxn * 4],rank[maxn];
    
    int cmp(QAQ x,QAQ y){
        return x.data < y.data;
    }
    
    void insert(int now,int l,int r,int x) {
        sum[now]++;
        if(l == r)
            return ;
        int mid = (l + r) >> 1;
        if(x <= mid)
            insert(now * 2,l,mid,x);
        else
            insert(now * 2 + 1,mid + 1,r,x);
    }
    
    int query(int now,int l,int r,int k) {
        if(l == r)
            return l;
        int mid = (l + r) >> 1;
        if(sum[now * 2] >= k)
            return query(now * 2,l,mid,k);
        else
            return query(now * 2 + 1,mid + 1,r,k - sum[now * 2]);
    }
    
    int main() {
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i].data);
            a[i].num = i;
        }
        sort(a + 1,a + n + 1,cmp);
        for(int i = 1; i <= n; i++)
            rank[a[i].num] = I;//这里的离散化就不太一样反正懂就好了www
        for(int i = 1; i <= n; i++) {
            insert(1,1,n,rank[i]);
            if(i % 2)
                printf("%d
    ",a[query(1,1,n,i / 2 + 1)].data);
        }
        return 0;
    }
    //道理都一样就是没有提前建树短一些23333
  • 相关阅读:
    jquery新知识
    jquery回顾
    Filter和Listener
    jsp,jstl,el
    cookie和session
    servlet和HTTP原理
    xml基本知识
    linux 相关操作
    linux mysql 相关操作、问题
    linux 文件结构
  • 原文地址:https://www.cnblogs.com/sevenyuanluo/p/10296046.html
Copyright © 2011-2022 走看看