【贪心】【set】zoj3963 Heap Partition

贪心地从前往后扫,每到一个元素,就查看之前的元素中小于等于其的最大的元素是否存在,如果存在,就将它置为其父亲。如果一个结点已经是两个儿子的父亲了,就不能在set中存在了,就将他删除。如果然后将当前元素插入。

如果不存在,就直接将当前元素插入。

哦,用pb_ds好像有点蠢,貌似set也能查询前驱……QAQ

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
#define INF 2147483647
vector<int>G[100010],prin[100010];
int T,n,a[100010];
typedef pair<int,int> Point;
tree<Point,null_type,less<Point>,rb_tree_tag,tree_order_statistics_node_update>S;
typedef tree<Point,null_type,less<Point>,rb_tree_tag,tree_order_statistics_node_update>::iterator ITER;
bool vis[100010];
int sum;
void dfs(int U){
	vis[U]=1;
	prin[sum].push_back(U);
	for(int i=0;i<G[U].size();++i){
		dfs(G[U][i]);
	}
}
int main(){
//	freopen("f.in","r",stdin);
	scanf("%d",&T);
	for(;T;--T){
		sum=0;
		memset(vis,0,sizeof(vis));
		S.clear();
		scanf("%d",&n);
		for(int i=1;i<=n;++i){
			G[i].clear();
		}
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
			ITER it=S.lower_bound(Point(a[i],i));
			if(it!=S.begin()){
				--it;
				G[(*it).second].push_back(i);
				if(G[(*it).second].size()==2){
					S.erase(it);
				}
				S.insert(Point(a[i],i));
			}
			else{
				S.insert(Point(a[i],i));
			}
		}
		for(int i=1;i<=n;++i){
			if(!vis[i]){
				++sum;
				dfs(i);
			}
		}
		printf("%d
",sum);
		for(int i=1;i<=sum;++i){
			sort(prin[i].begin(),prin[i].end());
			printf("%d ",prin[i].size());
			for(int j=0;j<prin[i].size()-1;++j){
				printf("%d ",prin[i][j]);
			}
			printf("%d
",prin[i][prin[i].size()-1]);
		}
		for(int i=1;i<=sum;++i){
			prin[i].clear();
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/6785218.html