洛谷P2251 质量检测
我为什么一看见这题就想用树状数组,又好写,又实用,多好。。。
nlogn建树,单词查询logn,对于100000的数据绰绰有余。
不过这好像和一般的树状数组不一样,一般都是求和,这次是求最值,变一下查询函数query。
//a[i]代表第i个数字,t[i]就是树状数组
//函数过程:每次强制让r指针进入下一棵子树(r--),在防止r指针出查询界限的同时(r-l>=lowbit(r)),
//不断跳跃(r-=lowbit(r)),并用r指针更新答案,直到剩余查询区间长度为0时退出(l==r)。
int query(int l,int r){
int ans=a[r];
while(1){
ans=min(ans,a[r]);
if(l==r)break;
for(r--;r-l>=lowbit(r);r-=lowbit(r)){
ans=min(ans,t[r]);
}
}
return ans;
}
除了这个,也没什么了。
我可能讲的不好,大家可以百度“树状数组求区间最值”,自己学。
下面是完整代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int a[1000001];
int t[1000001];
inline int lowbit(int x){
return x&-x;
}
void add(int i,int x){
while(i<=n){
t[i]=min(t[i],x);
i+=lowbit(i);
}
}
int query(int l,int r){
int ans=a[r];
while(1){
ans=min(ans,a[r]);
if(l==r)break;
for(r--;r-l>=lowbit(r);r-=lowbit(r)){
ans=min(ans,t[r]);
}
}
return ans;
}
int main(){
memset(t,0x3f,sizeof(t));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
add(i,a[i]);
}
for(int i=1,j=m;j<=n;i++,j++){
printf("%d\n",query(i,j));
}
return 0;
}