ZOJ 3963:Heap Partition(贪心+set+并查集)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3963

题意:给出一个n个数的序列,可以在其中找一个子序列建堆,并且堆中的父亲结点j和孩子结点i满足sj ≤ si and j < i。问要分配所有的数到堆里面,最少可以建多少个堆。

思路:对于每一个数,如果前面有小于等于它的数并且那个数的左右孩子还没满,那么就可以放在它的下面。考虑最优情况,就应该是每次插入到左右孩子还没满的,并且小于等于当前枚举的数的最大的数,然后插入到这个数后面。

因此可以用set来保存结点,每次都二分查找一下,如果没找到就建新的堆,找到了就插在它后面。

可以用并查集来保存关系。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 100010
 4 struct node {
 5     int val, id, cnt;
 6     bool operator < (const node &rhs) const {
 7         if(rhs.val != val) return val < rhs.val;
 8         if(rhs.id != id) return id > rhs.id; // 大的id优先,因为val相同的话,要使得二分可以返回val
 9         return cnt > rhs.cnt;
10     }
11 };
12 int fa[N], a[N];
13 set<node> se;
14 vector<int> ans[N];
15 
16 int Find(int x) { if(x == fa[x]) return x; return fa[x] = Find(fa[x]); }
17 
18 int main() {
19     int t; scanf("%d", &t);
20     while(t--) {
21         int n; scanf("%d", &n);
22         se.clear(); int k = 0;
23         for(int i = 1; i <= n; i++) scanf("%d", &a[i]), a[i] = -a[i], fa[i] = i;
24         for(int i = 1; i <= n; i++) {
25             node now = (node) { a[i], i, 2 };
26             set<node>::iterator it = se.lower_bound(now);
27             // lower_bound返回大于等于now的元素,设成负数,可以变成返回小于等于now的元素
28             if(it != se.end()) {
29                 int x = it->val, y = it->id, z = it->cnt;
30                 se.erase(it);
31                 if(z - 1) se.insert((node) {x, y, z - 1});
32                 fa[i] = Find(y);
33             }
34             se.insert(now);
35         }
36         for(int i = 1; i <= n; i++) if(fa[i] == i) ans[i].clear(), k++;
37         for(int i = 1; i <= n; i++) ans[Find(i)].push_back(i);
38         printf("%d
", k);
39         for(int i = 1; i <= n; i++) {
40             if(fa[i] != i) continue;
41             printf("%d", ans[i].size());
42             for(int j = 0; j < ans[i].size(); j++) printf(" %d", ans[i][j]);
43             puts("");
44         }
45     }
46     return 0;
47 }
原文地址:https://www.cnblogs.com/fightfordream/p/6759889.html