(这个题的idea好棒啊)
思路:
一个值 val 的插入最好就是在一个最接近他的值的结点x (权值x <= val) 上插入。
so,拿个 set 维护一下所有的结点,每次二分找一下。
还有要维护结点所能插的位置数量,不能插了要删除。
PS: set.upper_bound()好像是log(N)的
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<algorithm>
typedef long long LL;
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
const int N=1e5+10;
int n;
int node[N],cnt[N]; //node[] 代表结点位于树的编号,cnt[]代表该结点能插的个数
vector<int>ans[N]; //存答案
set<int>shu;
int num;
void init()
{
num = 0;
for(int i=0;i<=n;i++){
ans[i].clear();
cnt[i]=node[i]=0;
}
shu.clear();
}
void solve(int x,int pos)
{
set<int>::iterator it;
it=shu.upper_bound(x);
if(it == shu.begin()){
shu.insert(x);
cnt[x] = 2;
node[x] = num;
ans[num].push_back(pos);
num++;
}
else{
it--;
if(x != *it){
cnt[*it]--;
node[x] = node[*it];
if(!cnt[*it]) shu.erase(it);
shu.insert(x);
cnt[x] = 2;
ans[node[x]].push_back(pos);
}
else
{
cnt[x]++;
ans[node[x]].push_back(pos);
}
}
}
int main()
{
int T,x;
scanf("%d",&T);
while(T--){
init();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
solve(x,i);
}
printf("%d\n",num);
for(int i=0;i<num;i++)
{
int sz = ans[i].size();
printf("%d",sz);
for(int j=0;j<sz;j++)
printf(" %d",ans[i][j]);
puts("");
}
}
return 0;
}