洛谷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;
}
posted @ 2017-08-06 00:07  玫葵之蝶  阅读(96)  评论(0编辑  收藏  举报