JZOJ5405. 【NOIP2017提高A组模拟10.10】Permutation

来源:互联网 发布:jquery ajax post json 编辑:程序博客网 时间:2024/06/04 17:52

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序列中,可以交换的只有相邻的两个,
qiqi+1 才有可能可以进行交换。
而且,|qiqi+1|>=k
如果对于1..i中,都满足|qiqi1|>=k,那么i就可以被一直交换的1这个位置。
如果,在i的前面的某个位置j,不满足|qjqj1|>=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 998244353using 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');}
阅读全文
0 0