前言
t
a
g
:
tag :
tag: 贡献
连续子段的合法情况
滑动窗口
思维
传送门 :
题意 :
给定
n
,
k
n,k
n,k,同时给定一个数组
a
[
N
]
a[N]
a[N] , 询问数组中有多少个连续字段满足
2
0
a
i
<
2
1
a
i
+
1
<
.
.
.
.
<
2
k
a
i
+
k
2^0a_i<2^1a_{i+1}<....<2^ka_{i+k}
20ai<21ai+1<....<2kai+k
思路 :
我们考虑对 单独一个
i
i
i 进行考虑,如果
a
i
<
2
∗
a
i
+
1
a_i<2*a_{i+1}
ai<2∗ai+1
那么显然这个值对前面的数是合法的,我们考虑将其贡献设置为 1 1 1
显然,对于一个 [ i . . . i + k ] [i...i+k] [i...i+k]的子段,如果其 贡献的累积是 k k k 的话,就说明都符合条件,因此这样会对所求答案贡献 + 1 +1 +1
因为是连续子段,我们只需要 顺着枚举一下长度为 k + 1 k+1 k+1的区间即可
我们可以才用 加入队尾,弹出队头的操作,维护该长度的区间
code :
int n,k;
int a[N];
int st[N];
void solve(){
cin>>n>>k;
//for(int i=1;i<=n;i++) st[i] = 0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++){
st[i] = (a[i] < 2*a[i+1]);
}
int tot = 0 ;
for(int i=1;i<=k;i++){
tot+=st[i];
}
int res = 0 ;
if(tot == k) res++;
for(int i = k+1 ; i < n; i ++ ){
tot += st[i];
tot -= st[i-k];
if(tot == k) res++;
}
cout<<res<<endl;
}
int main(){
int t;cin>>t;while(t--)
solve();
return 0 ;
}