考场上队友写的据说是nlogn,然而并是超时,赛后听说题解是线段树区间优化建图,感觉挺神奇的特地写了一蛤。题意是模拟hash按顺序插数字,顺序寻址法,告诉你最后插完后的hash表,问你插入数字的顺序的最小字典序。于是对于每个插入的数字,算一蛤他原本的位置是在哪里,那么从原本的位置到他的上一个位置,都必须在他之前插入,于是我们想到了拓扑排序,但是由于他原本的位置距离他很远,直接连边会导致复杂度为n^2,但是我们使用线段树,叶子节点为1-n个位置,然后对于一个数字在i位置,原本位置在x,那么x到i-1的数字都要在i位置之前插入,那么直接就是这段区间连向第i个叶子节点,以达到拓扑排序的效果。注意,输入有可能不合法(我tm又不看清输出就写题,搞得我wa了好久),而且还有拓扑排序连边成环情况,都要输出-1
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxl 200010
#define inf 2000000001
using namespace std;
int n,cnt,tot,numcnt;
int ha[maxl],a[maxl],sum[maxl];
int ehead[maxl<<2],du[maxl<<2],dy[maxl<<2];
int ans[maxl];
struct node
{
int l,r,ind,num;
}tree[maxl<<2];
struct ed
{
int to,nxt;
}e[maxl<<4];
typedef pair<int,int> p;
priority_queue<p,vector<p>,greater<p> > q;
bool flag;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-f;ch=getchar();}
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void add(int u,int v)
{
e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;du[v]++;
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
if(l==r)
{
tree[k].ind=l;tree[k].num=ha[l];
du[l]=0;dy[l]=k;ehead[l]=0;
return;
}
tree[k].ind=++tot;tree[k].num=-1;
du[tot]=0;dy[tot]=k;ehead[tot]=0;
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
add(tree[k<<1].ind,tree[k].ind);
add(tree[k<<1|1].ind,tree[k].ind);
}
inline void linked(int k,int l,int r,int to)
{
if(tree[k].l==l && tree[k].r==r)
{
add(tree[k].ind,to);
return;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
linked(k<<1,l,r,to);
else
if(l>mid)
linked(k<<1|1,l,r,to);
else
{
linked(k<<1,l,mid,to);
linked(k<<1|1,mid+1,r,to);
}
}
inline void insert(int k)
{
if(du[tree[k].ind]==0)
q.push(make_pair(tree[k].num,tree[k].ind));
if(tree[k].l==tree[k].r)
return;
insert(k<<1);insert(k<<1|1);
}
inline void prework()
{
int x;
n=read();numcnt=0;
for(int i=1;i<=n;i++)
{
ha[i]=read();
if(ha[i]>=0)
numcnt++,sum[i]=sum[i-1]+1;
else
sum[i]=sum[i-1];
}
cnt=0;tot=n;
build(1,1,n);
flag=true;
for(int i=1;i<=n;i++)
if(ha[i]!=-1)
{
x=ha[i]%n+1;
if(i>x)
{
if(sum[i]-sum[x-1]==i-x+1)
linked(1,x,i-1,i);
else
{
flag=false;
return;
}
}
else
if(i<x)
{
if(sum[n]-sum[x-1]+sum[i]==i+n-x+1)
{
linked(1,x,n,i);
if(i>1)
linked(1,1,i-1,i);
}
else
{
flag=false;
return;
}
}
}
while(!q.empty()) q.pop();
insert(1);
}
inline void mainwork()
{
if(!flag) return;
p d;
int u,v,num;
ans[0]=0;
while(!q.empty())
{
d=q.top();q.pop();
num=d.first;u=d.second;
if(num>=0)
ans[++ans[0]]=num;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
du[v]--;
if(du[v]==0)
q.push(make_pair(tree[dy[v]].num,v));
}
}
if(ans[0]<numcnt)
flag=false;
}
inline void print()
{
if(!flag)
printf("-1\n");
else
if(ans[0]>0)
{
for(int i=1;i<ans[0];i++)
printf("%d ",ans[i]);
printf("%d\n",ans[ans[0]]);
}
else
printf("\n");
}
int main()
{
int t;
t=read();
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}