Problem:
Score : 2000 points

Problem Statement

You are given a permutation P_1 ... P_N of the set {1, 2, ..., N}.

You can apply the following operation to this permutation, any number of times (possibly zero):

Choose two indices i,j (1 ≦ i < j ≦ N), such that j - i ≧ K and |P_i - P_j| = 1.
Then, swap the values of P_i and P_j.

Among all permutations that can be obtained by applying this operation to the given permutation, find the lexicographically smallest one.

Constraints

2≦N≦500,000

1≦K≦N-1

P is a permutation of the set {1, 2, ..., N}.

Input

The input is given from Standard Input in the following format:

N K
P_1 P_2 ... P_N

Output

Print the lexicographically smallest permutation that can be obtained.

Sample Input 1

4 2
4 2 3 1

Sample Output 1

2
1
4
3

One possible way to obtain the lexicographically smallest permutation is shown below:

4 2 3 1

4 1 3 2

3 1 4 2

2 1 4 3

Sample Input 2

5 1
5 4 3 2 1

Sample Output 2

1
2
3
4
5

Sample Input 3

8 3
4 5 7 8 3 1 2 6

Sample Output 3

1
2
6
7
5
3
4
8

Solution in C++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <bits/stdc++.h>

using namespace std;

#define sz(x) ((int) ((x).size()))
typedef long long ll;
typedef long double ld;

mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
uniform_int_distribution<int> unii(0, 1 << 30);

int randNum() {
	return unii(rng);
}

struct treap {
	struct node {
		int size,prio,val;
		node *l=0,*r=0,*p=0;
	} *root=0;
	int get(node *n) { return n?n->size:0; }
	void upd(node *n) {
		if (n) {
			n->size=1+get(n->l)+get(n->r);
      if (n->l)
        n->l->p = n;
      if (n->r)
        n->r->p = n;
      n->p = 0;
    }
	}
	void split(node *n, node *&l, node *&r, int key, int add=0) {
		if (!n)
			return void(l=r=0);
		int nkey=add+get(n->l)+1;
		if (nkey<key)
			split(n->r,n->r,r,key,nkey),l=n;
		else
			split(n->l,l,n->l,key,add),r=n;
		upd(n);
	}
	void merge(node *l, node *r, node *&n) {
		if (!l||!r)
			n=l?l:r;
		else if (l->prio>r->prio)
			merge(l->r,r,l->r),n=l;
		else
			merge(l,r->l,r->l),n=r;
		upd(n);
	}
	node * insert(int pos, int val) {
		node *n=new node();
		n->prio=randNum(),n->val=val;
		node *l,*r;
		split(root,l,r,pos);
		merge(l,n,l);
		merge(l,r,root);
    return n;
	}
  int getPos(node * n) {
    if (n->p && n->p->l == n)
      return getPos(n->p) + get(n->l) - get(n);
    else if (n->p && n->p->r == n)
      return getPos(n->p) + get(n->l) + 1;
    else
      return get(n->l) + 1;
  }
	int get(int pos) {
		node *l,*n,*r;
		split(root,l,r,pos);
		split(r,n,r,2);
		int res=n?n->val:0;
		merge(l,n,l);
		merge(l,r,root);
		return res;
	}
} tr;

int n, k, p[600000], pos[600000];
treap::node * nodes[600000];

#define MAXN 500000
#define left(i) (2 * (i) + 1)
#define right(i) (2 * (i) + 2)
#define parent(i) (((i) - 1) / 2)
typedef int data;
typedef int operation;

const int logmaxn = (int) log2(MAXN) + 1;
const int ts = 1 << (logmaxn + 1), to = (1 << logmaxn) - 1;

data t[ts];
operation o[ts];

int getMax(int a, int b) {
  return a == -1 ? b : (b == -1 ? a : (tr.getPos(nodes[a]) > tr.getPos(nodes[b]) ? a : b));
}

// combine the data from different branches
data combine(data l, data r) {
  return getMax(l, r);
}

// // apply an operation on top of an other operation
// operation combine(operation ot, operation ob) {
//   return getMax(ot, ob);
// }

// apply an operation on a range with data
data apply(operation ot, data d) {
  return getMax(ot, d);
}

data getValue(int x) {
  return apply(o[x], t[x]);
}

void calcValue(int x) {
  t[x] = combine(getValue(left(x)), getValue(right(x)));
}

void propagate(int x) {
  o[left(x)] = combine(o[x], o[left(x)]);
  o[right(x)] = combine(o[x], o[right(x)]);
  o[x] = -1;
}

// query the data on the range [a, b[
data query(int a, int b, int x = 0, int l = 0, int r = 1 << logmaxn) {
  if (a <= l && r <= b)
    return getValue(x);
  if (b <= l || r <= a)
    return -1;
  int m = (l + r) / 2;
  propagate(x);
  data d = combine(query(a, b, left(x), l, m), query(a, b, right(x), m, r));
  calcValue(x);
  return d;
}

// apply an operation on the range [a, b[
void apply(int a, int b, operation v, int x = 0, int l = 0, int r = 1 << logmaxn) {
  if (a <= l && r <= b) {
    o[x] = combine(v, o[x]);
    return;
  }
  if (b <= l || r <= a)
    return;
  int m = (l + r) / 2;
  propagate(x);
  apply(a, b, v, left(x), l, m);
  apply(a, b, v, right(x), m, r);
  calcValue(x);
}

void build() {
	for (int i = 0; i < ts; i++)
		t[i] = o[i] = -1;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(10);
	build();
  cin >> n >> k;
  for (int i = 0; i < n; i++)
    cin >> p[i], p[i]--, pos[p[i]] = i;
  for (int i = 0; i < n; i++) {
    int inspos = 0;
    int j = query(0, pos[i] + k);
    if (j >= 0)
      inspos = max(inspos, tr.getPos(nodes[j]));
    nodes[pos[i]] = tr.insert(inspos + 1, pos[i]);
    apply(pos[i], pos[i] + 1, {pos[i]});
  }
  for (int i = 0; i < n; i++)
    pos[i] = tr.get(i + 1), p[pos[i]] = i;
  for (int i = 0; i < n; i++)
    cout << p[i] + 1 << "\n";
}