題意:
給定一個 n 個數的序列,存在一棵二叉樹他存放的元素滿足 ai <= aj && i<j (i爲 j 的父節點),要將這 n 個數全部都存到二叉樹中(可以不在同一棵樹),求最少需要多少棵樹。
每一個案例先輸出需要多少棵樹,
每棵樹的第一行輸出一個x,代表這棵樹有幾個元素,然後輸出這x個元素在原數組中的位置
題解:
對於每一個新插入的點,找前面≤它的最大點做爲它的父親。沒有就新建一個。 一個節點可以有兩個兒子。
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define mod 1000000007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
struct node
{
int v,id; // 值 下標
int k; //記錄屬於哪一顆樹
node(int a,int b,int c):v(a),id(b),k(c){}
bool operator < (node a)const
{
if(v==a.v)
return id<a.id;
return v<a.v;
}
};
int vis[maxn]; //標記
set<node> s;
set<node>::iterator it;
vector<int> v[maxn];
int main()
{
int t;
int n,x;
scanf("%d",&t);
while(t--)
{
int ans = 0; //有多少棵樹
s.clear();
scanf("%d",&n);
for(int i=0;i<=n;i++)
{
v[i].clear();
vis[i] = 0;
}
scanf("%d",&x);
s.insert(node(x,1,++ans));
v[ans].push_back(1);
for(int i=2;i<=n;i++)
{
scanf("%d",&x);
it = s.upper_bound(node(x,i,ans));
if(it==s.begin()) //如果 s 爲空 或者 第一個元素就比要插入的元素大(存入 s 的結構體已經從小到大排好序),就新建一個
{
s.insert(node(x,i,++ans));
v[ans].push_back(i);
}
else
{
it--;
node a = *it;
s.insert(node(x,i,a.k));
vis[a.id]++;
if(vis[a.id]==2)
s.erase(it);
v[a.k].push_back(i);
}
}
printf("%d\n",ans);
for(int i=1;i<=ans;i++)
{
int len = v[i].size();
printf("%d",len);
for(int j=0;j<len;j++)
printf(" %d",v[i][j]);
printf("\n");
}
}
return 0;
}