【优先队列】D. Constructing the Array
题意:给定一个长度为n的全0数组\(a\),每次进行以下操作直到所有元素均不为零:在第\(i\)次操作中,取最长的全为0的一段子序列(优先取最左边的),令\(a[\frac{len}{2}]=i\)。其中\(len\)为偶数,取\(l+r\)或\(l+r-1\)。
思路:
由于有个“优先”的问题,自然想到优先队列,需要重载一下运算符,使得长度最长且最左边的全零序列优先。
显然每次赋值都会使原序列切割成两个全0序列。
那么考虑一个结构体,记录全0序列的\(l\)与\(r\),以及顺序\(i\),作为结点加入队列。
int a[maxn];
struct node {
int l, r, len;
node(int a, int b, int c) {
l = a;
r = b;
len = c;
}
//优先队列从大到小排
//返回值为真意味着在队列排序中 this<a 成立
bool operator < (const node& a) const {
if (a.len == len) return l > a.l;
//如果长度相同而a的l较小(即靠近左边),则a>this(a更优先)
return len < a.len;
//否则如果a更长,则a>this(a更优先)
}
};
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) a[i] = 0;
priority_queue<node> q;
q.push(node(1, n, n));
for (int i = 1; i <= n; i++) {
node u = q.top();
q.pop();
int num = (u.len % 2) ? (u.l + u.r) / 2 : (u.l + u.r - 1) / 2;
a[num] = i;
q.push(node(u.l, num - 1, num - u.l));
q.push(node(num + 1, u.r, u.r - num));
}
for (int i = 1; i <= n; i++) cout << a[i] << " ";
cout << endl;
}