zoukankan      html  css  js  c++  java
  • ZOJ 3963 Heap Partition(multiset + stl自带二分 + 贪心)题解

    题意:给你n个数字s1~sn,要你把它们组成一棵棵二叉树,对这棵二叉树来说,所有节点来自S,并且父节点si<=子节点sj,并且i<j,问你树最少几棵二叉数、树

    思路:贪心。我们往multiset加还能加子节点的节点,二分查找一个个大于等于当前插入节点的节点,然后插入,若找不到则重新建一棵树。

    没想到set自带lower_bound(),第一次迭代器遍历TLE就想着手动写二分...然后发现自带二分...

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<set>
    #include<vector>
    #include<string.h>
    #include<algorithm>
    typedef long long int ll;
    using namespace std;
    const int maxn = 1e5 + 5;
    const int inf = 0x3f3f3f3f;
    const ll mod = 1e9 + 7;
    vector<int> G[maxn];
    struct node{
        int id, sz, num;
    };
    struct compare{
        bool operator () (node a, node b){
            return a.sz > b.sz;
        }
    };
    node add(int id, int sz){
        node a;
        a.id = id , a.sz = sz, a.num = 0;
        return a;
    }
    multiset<node, compare> q;
    int main(){
        int T, a;
        scanf("%d", &T);
        while(T--){
            q.clear();
            int n;
            scanf("%d", &n);
            scanf("%d", &a);
            int cnt = 2;
            q.insert(add(1, a));
            G[1].clear();
            G[1].push_back(1);
            node p;
            for(int i = 2; i <= n; i++){
                scanf("%d" ,&a);
                multiset<node>::iterator it;
                p.sz = a;
                it = q.lower_bound(p);
                if(it == q.end()){
                    q.insert(add(cnt, a));
                    G[cnt].clear();
                    G[cnt].push_back(i);
                    cnt++;
                }
                else{
                    p = *it;
                    q.erase(it);
                    p.num++;
                    if(p.num < 2)
                        q.insert(p);
                    q.insert(add(p.id, a));
                    G[p.id].push_back(i);
                }
            }
            printf("%d
    ", cnt - 1);
            for(int i = 1; i < cnt; i++){
                int len = G[i].size();
                printf("%d", len);
                for(int j = 0; j < len; j++)
                    printf(" %d", G[i][j]);
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    SQL Sever语言 存储过程及触发器
    计蒜客 挑战难题 移除数组中的重复元素
    projecteuler Sum square difference
    码农谷 求前N项之和
    projecteuler Smallest multiple
    计蒜客 挑战难题 寻找插入位置
    Largest palindrome product
    计蒜客 挑战难题 元素移除
    码农谷 球从M米高度自由下落第N次落地时反弹的高度
    挑战难题 奇怪的国家
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9926387.html
Copyright © 2011-2022 走看看