ZOJ 3963 Heap Partition(multiset + stl自帶二分 + 貪心)題解
阿新 • • 發佈:2018-11-07
題意:給你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{ intid, 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; }