题目简介:每次在数组中插入数字,如果该位置已经有了元素,就把后面的所有元素一次往后移动
分析:
一开始我用块状链表搞,但是因为每个位置有一个初始值0,因此第一次插入的时候会有覆盖操作
我就在想,可不可以第一次插入的时候先删除,后插入
但是这样会出现一个问题:
如果在一个位置插入了过多元素,后边的位置就会有元素了,这样在后面的位置插入的时候就不用删除了
于是我又开了一个数组,表示每个位置插入了多少元素,插入元素个数会影响之后的位置
但是这样产生了另一个问题:两个相隔不远的位置插入的元素元素过多,那么互相就会影响(反正后果就是WA。。。)
这道题的正解是:并查集+块状链表
tip
不写快读会WA
(代码中没写。。懒。。治不了)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=300000;
const int blocksize=700;
const int blocknum=700;
struct node{
int size,nxt,pre;
int data[blocksize+100];
};
node a[blocknum];
int n,m,cnt,tot,f[N],q[N],top=0;
void find(int pos,int &p,int &num)
{
int sum=0;
p=1;
while (sum+a[p].size<pos&&a[p].nxt) sum+=a[p].size,p=a[p].nxt;
num=pos-sum;
}
int findfa(int x)
{
if (f[x]!=x) f[x]=findfa(f[x]);
return f[x];
}
void change(int pos,int x)
{
int p,num;
find(pos,p,num);
a[p].data[num]=x;
}
void del(int pos)
{
int p,num;
find(pos,p,num);
for (int i=num;i<=a[p].size;i++) a[p].data[i]=a[p].data[i+1];
a[p].size--;
}
void insert(int pos,int x)
{
int p,num;
find(pos,p,num);
if (a[p].size==blocksize)
{
cnt++;
a[cnt].pre=p; a[cnt].nxt=a[p].nxt; a[cnt].size=a[p].size-num+1;
a[a[p].nxt].pre=cnt; a[p].nxt=cnt;
for (int i=num;i<=a[p].size;i++) a[cnt].data[i-num+1]=a[p].data[i];
a[p].size=num-1;
if (a[p].size>a[cnt].size) num=1,p=cnt;
}
for (int i=a[p].size;i>=num;i--) a[p].data[i+1]=a[p].data[i];
a[p].data[num]=x;
a[p].size++;
}
void work()
{
for (int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
int pos=findfa(t); //并查集的标志结点
if (pos==t) change(pos,i); //添加
else
{
if (pos<=tot) del(pos); //第一次插入时我们需要删除原先的占位结点
else tot++;
insert(t,i);
}
f[pos]=f[pos+1];
}
}
void print(int nn)
{
int t=1;
top=0;
while (t&&nn)
{
for (int i=1;i<=a[t].size&&nn;i++)
{
q[++top]=a[t].data[i];
if (q[top]) nn--;
}
t=a[t].nxt;
}
printf("%d\n",top);
for (int i=1;i<top;i++) printf("%d ",q[i]);
printf("%d\n",q[top]);
}
int main()
{
scanf("%d%d",&n,&m);
tot=m; cnt=0; //块的个数
for (int i=1;i<=max(n+m,m*2);i++) f[i]=i; //并查集
while (m>blocksize) //数组下标范围
{
m-=blocksize;
cnt++; a[cnt].pre=cnt-1; a[cnt-1].nxt=cnt; a[cnt].size=blocksize;
}
cnt++; a[cnt].pre=cnt-1; a[cnt-1].nxt=cnt; a[cnt].size=m;
work();
print(n);
return 0;
}