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;
}