思维题
我现在非常喜欢的题(因为之前被思维题弄死了。
虽然这次没想出来,看了题解才会的。
其实非常简单,只需要掌握一个核心思想:
假如
i
i
i最远能到
j
j
j,那么
i
+
1
i+1
i+1最远起码到
j
j
j
因为
i
+
1
i+1
i+1开始的前缀最大值会更小,就更能走的更远,起码到
j
j
j。
并且,如果走的长度是有限的话,是不会超过 2 n 2n 2n的,因为第一遍刚得到最值,可能后面的最大值会让前面的不满足要求,所以再跑一点才会不合法,最多是 2 n 2n 2n的,应该是到不了 2 n 2n 2n否则就是无限了。
我们化环为链即可。对于区间最值可以用
S
T
ST
ST表快速做,(单调队列应该也可以做。
具体处理是
O
(
n
)
O(n)
O(n)的
#include<bits/stdc++.h>
using namespace std;
vector<int> v;
typedef long long ll;
const int maxn = 3e5+500;
#define maxk 21
int st[maxn][maxk];
int p[maxn],a[maxn],tmp,n;
void ST_init(){
for(int i=1;i<=n;i++){
st[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i<=n;i++){
st[i][j]=max(st[i][j-1],st[min(n,i+(1<<(j-1)))][j-1]);
}
}
p[0]=-1;for(int i=1;i<=n;i++)p[i]=p[i>>1]+1;
}
inline int getmax(int l,int r){
int t=p[r-l+1];
return max(st[l][t],st[r-(1<<t)+1][t]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[n+i]=a[i];
a[2*n+i]=a[i];
}
n*=3;
ST_init();
int now=0;
for(int i=1;i<=n/3;i++){
int j=now;
while(j<n){
if(getmax(i,j+1)<=2*a[j+1]){
j++;
}
else break;
}
now=j;
int ans=now-i+1;
if(now==n)ans=-1;
printf("%d%c",ans,i==n/3?'\n':' ');
}
}