ZOJ 3963 Heap Partition(贪心)

来源:互联网 发布:二维码生成软件设备 编辑:程序博客网 时间:2024/06/06 01:28

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, sjsi 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 , sjsij<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("%d\n", 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();        }    }}
0 0
原创粉丝点击