Solution - CF1237D

Soulution.

先将原数组复制三份。

然后,我们可以用一个单调递减队列来维护 KUN 值。当某个时刻发现队首元素 \(a_i\) 除以 \(2\) 比队尾元素 \(j\) 大,这就表明了 \(i\) 元素以前已经被弹出的元素都将会在 \(j\) 处暂停播放音乐。于是我们就用数组记录答案,然后 \(i\) 以前的元素都可以通过 \(i\) 推出来。(弹出队首时我们要用 while ,因为可能有多个队首都不满足条件)。

Code.

#include <bits/stdc++.h>
using namespace std;
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}
int n;
int a[300005];
int q[300005], tail = 0, head = 0;//单调队列
int ans[300005];
signed main() {
	freopen("playlist.in", "r", stdin);
	freopen("playlist.out", "w", stdout);
	read(n);
	for (int i = 1; i <= n; i++) {
		read(a[i]);
	}
	for (int i = 1; i <= n; i++) {
		a[i + n] = a[i];
	}
	for (int i = 1; i <= n; i++) {//复制三份
		a[i + 2 * n] = a[i];
	}
	for (int i = 1; i <= 3 * n; i++) {
		while (head <= tail && a[q[tail]] < a[i]) tail--;//维护单调递减
		q[++tail] = i;
		while (a[q[head]] * 1.0 / 2 > a[q[tail]]) {//弹出队首
			ans[q[head]] = i - q[head];
			head++;
		}
	}
	for (int i = 3 * n; i >= 1; i--) {
		if (ans[i] == 0 && ans[i + 1] != 0) ans[i] = ans[i + 1] + 1;
	}
	for (int i = 1; i <= n; i++) {
		if (ans[i] == 0) print(-1, ' ');
		else print(ans[i], ' ');
	}
	return 0;
}
上一篇:《Unix/Linux系统编程》第十二章学习笔记


下一篇:c++仿照go语言的error,函数返回值封装