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; }