我是靠谱客的博主 怡然月饼,最近开发中收集的这篇文章主要介绍ZOJ 3963 Heap Partition(贪心),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

A sequence S={s1,s2,...,sn} is called heapable if there exists a binary tree T with n nodes such that every node is labelled with exactly one element from the sequence S, and for every non-root node si and its parent sj , sj si and j < i hold. Each element in sequence S can be used to label a node in tree T only once.

Chiaki has a sequence a1,a2,...,an , she would like to decompose it into a minimum number of heapable subsequences.

Note that a subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.

序列 S={s1,s2,...,sn} 被称为 heapable ,当且仅当存在一个二叉树 T , n 个点均作为 T 的一个节点,且满足任意非根节点 si 和其父节点 sj , sjsi j<i

现在有一个序列 a1,a2,...,an ,相应将其分成若干个 heapable 的子序列,问使得子序列个数最少的策略。

解题思路

已知每个树上的节点 sj 均可有最多两个子节点 si ,要求 sjsi 。将所有仍可连接子节点的节点用一个 set 来维护,保证其根据点对应的 ai 从小到大排序。对于一个新的 ai 来说,采用贪心策略将其作为最大的不大于 ai 值的节点的子节点,用 set.upper_bound() 可以在 O(set.size()) 复杂度内实现查找。

需要注意的是,每个节点最多只能有两个子节点,故当某节点已经连接了两个子节点后,应将其从 set 中删除。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 10;
vector<int> v[N];
int n, a[N], cnt, dig[N];
struct Node {
    int first, second;
} p;
bool operator<(Node x, Node y)
{
    if(a[x.second] == a[y.second])    return x.second < y.second;
    return a[x.second] < a[y.second];
}
set<Node > st;
set<Node >::iterator it;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        st.clear();
        cnt = 0;
        scanf("%d",&n);
        memset(dig, 0, 4*n+4);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            p.second = i;
            it = st.upper_bound(p);
            if(it==st.begin())
            {
                v[cnt].push_back(i);
                p.first = cnt,  p.second = i;
                st.insert(p);
                cnt++;
            }
            else
            {
                it--;
                p = *it;
                dig[p.second]++;
                if(dig[p.second] == 2)
                    st.erase(it);
                p.second = i;
                st.insert(p);
                v[p.first].push_back(i);
            }
        }
        printf("%dn", cnt);
        for(int i=0;i<cnt;i++)
        {
            printf("%d", v[i].size());
            for(int j=0;j<v[i].size();j++)
                printf(" %d", v[i][j]);
            printf("n");
            v[i].clear();
        }
    }
}

最后

以上就是怡然月饼为你收集整理的ZOJ 3963 Heap Partition(贪心)的全部内容,希望文章能够帮你解决ZOJ 3963 Heap Partition(贪心)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(94)

评论列表共有 0 条评论

立即
投稿
返回
顶部