贪心地从前往后扫,每到一个元素,就查看之前的元素中小于等于其的最大的元素是否存在,如果存在,就将它置为其父亲。如果一个结点已经是两个儿子的父亲了,就不能在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; }