bzoj 1699 [Usaco2007 Jan]Balanced Lineup排队

链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1699

 

思路:

水题,求区间最大最小值,然后减一下,求区间最大最小值线段树,树状数组,分块,莫队都可以,这里直接用分块写了,代码量比较小。

 

分块写法:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5+10;
const int inf = 1e9+10;
int n,m,a[M],mn[M],mx[M],bl[M],block;
int query(int l,int r){
    int ans,maxx = 0,minn = inf;
    for(int i = l;i <= min(bl[l]*block,r);i ++){
        minn = min(minn,a[i]);
        maxx = max(maxx,a[i]);
    }
    if(bl[l] != bl[r]){
        for(int i = (bl[r]-1)*block+1;i <= r;i ++){
            minn = min(minn,a[i]);
            maxx = max(maxx,a[i]);
        }
    }
    for(int i = bl[l] + 1;i <= bl[r]-1;i ++){
        minn = min(mn[i],minn);
        maxx = max(mx[i],maxx);
    }
    return maxx - minn;
}

int main()
{
    int l,r;
    scanf("%d%d",&n,&m);
    block = sqrt(n);
    memset(mn,inf,sizeof(mn));
    for(int i = 1;i <= n;i ++) scanf("%d",&a[i]);
    for(int i = 1;i <= n;i ++){
        bl[i] = (i - 1)/block + 1;
        mn[(i-1)/block+1] = min(a[i],mn[(i-1)/block+1]);
        mx[(i-1)/block+1] = max(a[i],mx[(i-1)/block+1]);
    }
    for(int i = 1;i <= m;i ++){
        scanf("%d%d",&l,&r);
        printf("%d\n",query(l,r));
    }
    return 0;
}

耗时:

posted @ 2018-07-29 13:44  冥想选手  阅读(134)  评论(0编辑  收藏  举报