用数组结构体存每一个块,块中每一个数的序号用队列存,合并的时候将队列中的数合并。
O(nn) 的做法。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
struct BLOCK {
int leng;
int id;
bool bg;
queue<int> q;
}a[N];
bool used[N];
int n, bgg, len = 1, id = 1, tot = 0;
int main () {
scanf ("%d%d", &n, &bgg);
bool bg;
if (bgg == 0) {
bg = false;
}
else {
bg = true;
}
a[++ tot].id = 1;
a[tot].bg = bg;
bool fg = bg;
for (int i = 2, t; i <= n; i ++) {
scanf ("%d", &t);
if (t != bgg) {
a[tot].leng = len;
a[++ tot].id = i;
fg = (! fg);
a[tot].bg = fg;
len = 1;
bgg = (! bgg);
}
else {
len ++;
}
}
a[tot].leng = len;
int all = 0;
a[0].leng = 1919810;
a[n + 1].leng = 1919810;
for (int i = 1; i <= tot; i ++) {
for (int j = a[i].id; j <= a[i].id + a[i].leng - 1; j ++) {
a[i].q.push (j);
}
}
memset (used, false, sizeof (used));
while (1) {
if (a[1].leng == 0) {
used[1] = true;
}
if (a[tot].leng == 0) {
used[tot] = true;
}
for (int i = 2; i < tot; i ++) {
if (a[i].leng == 0 && used[i] == false) {
int fi = i - 1, se = i + 1;
used[i] = true;
while (1) {
if (a[fi].leng >= 1 && used[fi] == false) {
break;
}
fi --;
}
while (1) {
if (a[se].leng >= 1 && used[se] == false) {
break;
}
se ++;
}
if (a[fi].leng == 1919810 || a[se].leng == 1919810) {
break;
}
if (a[fi].bg == a[se].bg) {
a[fi].leng += a[se].leng;
a[se].leng = 0;
while (!a[se].q.empty()) {
a[fi].q.push (a[se].q.front ());
a[se].q.pop ();
}
used[se] = true;
}
}
}
for (int i = 1; i <= tot; i ++) {
if (a[i].leng >= 1 && used[i] == false) {
a[i].leng --;
printf ("%d ", a[i].q.front ());
all ++;
a[i].q.pop ();
}
}
if (all == n) {
return 0;
}
printf ("\n");
}
}