Description
你有一个长度为n 的排列P 与一个正整数K
你可以进行如下操作若干次使得排列的字典序尽量小
对于两个满足|i-j|>=K 且|Pi-Pj| = 1 的下标i 与j,交换Pi 与Pj
Input
第一行包括两个正整数n 与K
第二行包括n 个正整数,第i 个正整数表示Pi
Output
输出一个新排列表示答案
输出共n 行,第i 行表示Pi
Sample Input
8 3
4 5 7 8 3 1 2 6
Sample Output
1
2
6
7
5
3
4
8
Data Constraint
对于前20% 的数据满足n <= 6
对于前50% 的数据满足n <= 2000
对于100% 的数据满足n <= 500000
题解
因为有|Pi-Pj| = 1,意思就是只有P的值是相邻的才能交换。
我们构造一个新的序列:
qpi=i
那么在q序列中,可以交换的只有相邻的两个,
即
qi和qi+1
才有可能可以进行交换。
而且,
|qi−qi+1|>=k
如果对于1..i中,都满足
|qi−qi−1|>=k
,那么i就可以被一直交换的1这个位置。
如果,在i的前面的某个位置j,不满足
|qj−qj−1|>=k
那么,i最多只能被交换到j的位置。
这就说明了它们的位置的相对顺序是不会改变的。
根据这个相对顺序来连边,
然后跑一边拓扑序,注意一下最小值就可以了。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 500003
#define db double
#define P putchar
#define G getchar
#define mo 998244353
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
db max(db a,db b){return a>b?a:b;}
db min(db a,db b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
struct node{int x;}t;
priority_queue <node> d;
bool operator <(node a,node b)
{
return a.x<b.x;
}
int n,k,ans[N],x,p[N],q[N];
int nxt[N*2],f[N],to[N*2],b[N],tot;
int tr[N*4],opl,opr,opx,ops;
void work(int x,int l,int r)
{
if(opl<=l && r<=opr)
{
if(opx==1)ops=min(ops,tr[x]);
if(opx==2)tr[x]=ops;
return;
}
int m=(l+r)>>1;
if(opl<=m)work(x+x,l,m);
if(m<opr)work(x+x+1,m+1,r);
tr[x]=min(tr[x+x],tr[x+x+1]);
}
void ins(int x,int y)
{
nxt[++tot]=b[x];
to[tot]=y;
b[x]=tot;
f[y]++;
}
int main()
{
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
read(n);read(k);memset(tr,127,sizeof(tr));
for(int i=1;i<=n;i++)
read(p[i]),q[p[i]]=i;
for(int i=n;i;i--)
{
opl=q[i]-k+1;opr=q[i];opx=1;ops=n+1;
work(1,1,n);
if(ops<n+1)ins(q[ops],q[i]);
opl=q[i];opr=q[i]+k-1;opx=1;ops=n+1;
work(1,1,n);
if(ops<n+1)ins(q[ops],q[i]);
opl=q[i];opr=q[i];opx=2;ops=i;
work(1,1,n);
}
for(int i=1;i<=n;i++)
if(f[i]==0)t.x=i,d.push(t);
for(int i=n;i;i--)
{
t=d.top();d.pop();x=t.x;p[i]=x;
for(int i=b[x];i;i=nxt[i])
{
f[to[i]]--;
if(f[to[i]]==0)t.x=to[i],d.push(t);
}
}
for(int i=1;i<=n;i++)
q[p[i]]=i;
for(int i=1;i<=n;i++)
write(q[i]),P('\n');
}