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\n", 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("\n");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/9926387.html

时间: 2024-10-09 12:34:28

ZOJ 3963 Heap Partition(multiset + stl自带二分 + 贪心)题解的相关文章

zoj 3963 Heap Partition(贪心)

Heap Partition Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge 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 se

zoj 3963 heap partion

https://vjudge.net/problem/ZOJ-3963 题意: 给出一个数列,可以用这个数列构造一种二叉树,这个二叉树满足数的下标 i <= j,并且 si <= sj,si是sj的父亲,问给出的数列可以构造多少棵这样的二叉树. 思路: 这题赛上没有写出来,看了题解之后给补的. 首先,通过这题学到了,memset初始化数组有时是会造成超时的.set的upper_bound(x)这个函数,它返回set中大于x的第一个元素的位置(注意是大于,不是大于等于). 于是,这题就是贪心加s

SPOJ ADAFIELD Ada and Field(STL的使用:set,multiset,map的迭代器)题解

题意:n*m的方格,"0 x"表示x轴在x位置切一刀,"0 y"表示y轴在y位置切一刀,每次操作后输出当前面积最大矩形. 思路:用set分别储存x轴y轴分割的点,用multiset(可重复)储存x轴y轴边,每次输出最大的长和最大的宽的积.题目可能重复切.multiset如果直接erase(13)会把所有的13都删掉,如果只想删一个则erase(multiset.find(13)).第一次知道set自带二分... 这里multiset也可以用map<int, i

STL中的二分查找———lower_bound,upper_bound,binary_search

关于STL中的排序和检索,排序一般用sort函数即可,今天来整理一下检索中常用的函数——lower_bound , upper_bound 和 binary_search . STL中关于二分查找的函数有三个lower_bound .upper_bound .binary_search .这三个函数都运用于有序区间(当然这也是运用二分查找的前提). Tips:1.在检索前,应该用sort函数对数组进行从小到大排序.     2.使用以上函数时必须包含头文件:#include < algorith

ZOJ 1516 Uncle Tom&#39;s Inherited Land(二分匹配 最大匹配 匈牙利啊)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=516 Your old uncle Tom inherited a piece of land from his great-great-uncle. Originally, the property had been in the shape of a rectangle. A long time ago, however, his great-great-uncl

zoj 3659 Conquer a New Region 并查集+贪心

点击打开链接题目链接 Conquer a New Region Time Limit: 5 Seconds      Memory Limit: 32768 KB The wheel of the history rolling forward, our king conquered a new region in a distant continent. There are N towns (numbered from 1 to N) in this region connected by s

STL中的二分查找——lower_bound 、upper_bound 、binary_search

STL中的二分查找函数 1.lower_bound函数 在一个非递减序列的前闭后开区间[first,last)中,进行二分查找查找某一元素val,函数lower_bound()返回大于或等于val的第一个元素位置(即满足条件a[i]>=val(first<=i<last)的最小的i的值),当区间的所有元素都小于val时,函数返回的i值为last(注意:此时i的值是越界的!!!!!). 比如:已知数组元素是a[10]={0,2,2,2,6,8,10,16,60,100} 当val=0时,函

STL中的二分查找

本文转载于https://blog.csdn.net/riba2534/article/details/69240450 使用的时候注意:必须用在非递减的区间中 二分查找的原理非常简单,但写出的代码中很容易含有很多Bug,二分查找一文中讲解过如何实现不同类型的二分查找,但是否一定要自己去实现二分查找呢?答案显然是否定的,本文将讲解STL中与二分查找有关函数的具体使用方法及其实现原理. 函数使用 STL中与二分查找相关的函数有4个,分别是lower_bound, upper_bound, equa

C++ STL中的二分查找

这篇博客转自爱国师哥,这里给出连接https://www.cnblogs.com/aiguona/p/7281856.html 一.解释 以前遇到二分的题目都是手动实现二分,不得不说错误比较多,关于返回值,关于区间的左闭右开等很容易出错,最近做题发现直接使用STL中的二分函数方便快捷还不会出错,不过对于没有接触过的同学,二分函数确实是一个头疼的部分,自己查的内容又有点乱,找不到具体的使用方法,有必要自己总结一份完整的以后备用. 二.常用操作 1.头文件 #include <algorithm>