zoukankan      html  css  js  c++  java
  • 牛客:CBX and children(平衡树+二分+贪心)

    题意:

    众所周知,CBX是一个非常喜欢和孩子们玩耍的男孩。一天,CBX和n个孩子在玩捉迷藏游戏操场。每孩子有一个身高(整数),每个孩子都可以躲在另一个孩子的后面,前提是他后面的孩子至少是他身后孩子的两倍。

    每个孩子只能躲在一个孩子的后面,而躲在其他孩子的后面不能隐藏孩子。

    假设躲在其他人后面的孩子不会被CBX看到,找到一个计划,让CBX看到最少的孩子

    题解;

    有一个显然的贪心思路是,每次选取大于等于x*2的最小的那个人,把x放在他的后面。但是这样好像无法保证正确性,再在这个基础上二分答案。

    具体做法是:每次选取mid个人作为可以被看到的,对于剩下的人,找到大于等于他的身高的两倍的最矮的被看到的人作为遮挡,最后看看能否挡住剩下的所有人。

    二分内check这个过程很多数据结构都可以实现,这里我使用的是Treap树。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+100;
    const int inf=1e9;
    //treap树
    //利用BST的性质做查询和修改
    //利用随机和堆优先级来保持平衡
    struct Treap_tree {
        int ch[2];
        int v;
        int dat;//优先级 
        int size;//子树节点数 
        int cnt;//重复数 
    }t[maxn];
    int tot;
    int root;
    int newNode (int v) {
        tot++;
        t[tot].v=v;
        t[tot].dat=rand();//随机优先级
        t[tot].size=1;
        t[tot].cnt=1;
        t[tot].ch[0]=0;
        t[tot].ch[1]=0;
        return tot; 
    } 
    void pushup (int x) {
        t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
    }
    void build () {
        root=newNode(-inf);
        t[root].ch[1]=newNode(inf);
        pushup(root);
    }
    void rotate (int &id,int d) {
        int tt=t[id].ch[d^1];
        t[id].ch[d^1]=t[tt].ch[d];
        t[tt].ch[d]=id;
        id=tt;
        pushup(t[id].ch[d]);
        pushup(id);
    }
    void ins (int &id,int v) {
        if (!id) {
            id=newNode(v);
            return;
        }
        if (v==t[id].v) t[id].cnt++;
        else {
            ins(t[id].ch[v>t[id].v],v);
            if (t[id].dat<t[t[id].ch[v>t[id].v]].dat) rotate(id,v<t[id].v);
        }
        pushup(id);
    }
    void remove (int &id,int v) {
        if (!id) return;
        if (v==t[id].v) {
            if (t[id].cnt>1) {
                t[id].cnt--;
                pushup(id);
                return;
            }
            if (t[id].ch[0]||t[id].ch[1]) {
                if (!t[id].ch[1]||t[t[id].ch[0]].dat>t[t[id].ch[1]].dat) {
                    rotate(id,1);
                    remove(t[id].ch[1],v);
                }
                else {
                    rotate(id,0);
                    remove(t[id].ch[0],v);
                }
                pushup(id);
            }
            else
                id=0;
            return;
        }
        remove(t[id].ch[v>t[id].v],v);
        pushup(id);
    }
    int rk (int id,int v) {
        if (!id) return 0;
        if (v==t[id].v) 
            return t[t[id].ch[0]].size+1;
        else if (v<t[id].v)
            return rk(t[id].ch[0],v);
        else
            return t[t[id].ch[0]].size+t[id].cnt+rk(t[id].ch[1],v);
    }
    int kth (int id,int k) {
        if (!id) return inf;
        if (k<=t[t[id].ch[0]].size)
            return kth(t[id].ch[0],k);
        else if (k<=t[t[id].ch[0]].size+t[id].cnt)
            return t[id].v;
        else
            return kth(t[id].ch[1],k-t[t[id].ch[0]].size-t[id].cnt);
    }
    int get_pre (int id,int v) {
        int pre;
        while (id) {
            if (t[id].v<v)
                pre=t[id].v,id=t[id].ch[1];
            else
                id=t[id].ch[0];
        }
        return pre;
    }
    int get_next (int id,int v) {
        int nxt;
        while (id) {
            if (t[id].v>v)
                nxt=t[id].v,id=t[id].ch[0];
            else
                id=t[id].ch[1];
        }
        return nxt;
    }
    int a[maxn];
    int main () {
        int n;
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",a+i);
        sort(a+1,a+n+1);
        int ans=-1;
        int l=1,r=n;
        while (l<=r) {
            int mid=(l+r)>>1;
            tot=0;
            build();
            for (int i=n;i>n-mid;i--) ins(root,a[i]);
            int tt=mid;
            for (int i=1;i<=n-mid;i++) {
                int nxt=get_next(root,a[i]*2-1);
                if (nxt==inf) continue;
                tt++;
                remove(root,nxt);
            }
            if (tt==n) {
                ans=mid;
                r=mid-1;
            }
            else {
                l=mid+1;
            }
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    dd——留言板再加验证码功能
    怎样去除织梦版权信息中的Power by DedeCms
    数据结构和算法的选择
    数据结构和算法9——哈希表
    数据结构与算法8——二叉树
    数据结构与算法7——高级排序
    数据结构与算法6——递归
    数据结构和算法5——链表
    数据结构与算法4——栈和队列
    数据结构与算法3——简单排序(冒泡、选择、插入排序)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13668767.html
Copyright © 2011-2022 走看看