思路分析:若前面的维护的数已按小到大排好序,每次找到左边第一个小于等于素该元的数插入,如果标记插入次数>=2,
则从中删除。用set或权值线段树维护即可。
!!!!nlog(n)的算法TLE了很多发,加上各种读优化仍旧TLE,懵逼逼。。。不知羞耻地上网看了别人的代码,发现T在了
memset 上面,把 sizeof()改为 4*n+4就过了。。。 涨姿势了。。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
struct Q{
int v,x;
}A[100010];
vector<int>g[100010];
set<int>s;
set<int>::iterator it;
int vis[100010],bel[100010],B[100010],cnt[100010];
int main(){
int t,i,j,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(vis,0,4*n+4);
memset(bel,0,4*n+4);
memset(cnt,0,4*n+4);
for(i=0;i<=n;i++) g[i].clear();
s.clear();
for(i=1;i<=n;i++){
scanf("%d",&A[i].v);
cnt[A[i].v]++;
}
for(i=1;i<=n;i++) cnt[i]+=cnt[i-1];
for(i=n;i>=1;i--){
A[i].x=cnt[A[i].v]--;
B[A[i].x]=i;
}
int k=0;
for(i=1;i<=n;i++){
if(s.size()==0||*s.begin()>A[i].x) bel[i]=k++;
else{
it=s.lower_bound(A[i].x);
it--;
bel[i]=bel[B[*it]];
vis[*it]++;
if(vis[*it]==2) s.erase(*it);
}
s.insert(A[i].x);
}
for(i=1;i<=n;i++){
g[bel[i]].push_back(i);
}
printf("%d\n",k);
for(i=0;i<k;i++){
printf("%d",g[i].size());
for(j=0;j<g[i].size();j++) printf(" %d",g[i][j]);
printf("\n");
}
}
return 0;
}