【优先队列】D. Constructing the Array

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;
}
posted @ 2020-05-15 21:56  StreamAzure  阅读(451)  评论(0编辑  收藏  举报