洛谷P1816 忠诚 分块

分块真的是很暴力呀…
暴力查询左端,暴力查询又端点,中间整体部分直接 $O(1)$ 求出。
注意编程细节:belong[i]=(i−1)/block+1,这样可以保证序列被分成这样的:
Code:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1000000;
const int inf = 100000000;
int n,m;
struct Data_Structrue{
    int arr[maxn], minv[maxn], belong[maxn]; 
    int block; 
    inline void build(){
        memset(minv, 127, sizeof(minv)); 
        scanf("%d%d",&n,&m);
        block = sqrt(n);
        for(int i = 1;i <= n; ++i){ 
            scanf("%d",&arr[i]); 
            belong[i] = (i - 1)/ block + 1;
            minv[belong[i]] = min(minv[belong[i]], arr[i]);
        }
    }   
    inline int query(int l,int r){
        int minn = inf;
        for(int i = l;i <= min(belong[l] * block, r); ++i) minn = min(minn, arr[i]);       //暴力查询左端(可能已经查询完毕)
        if(belong[l] != belong[r])
        {
            for(int i = (belong[r] - 1) * block + 1;i <= r; ++i)                           //暴力查询右端
                minn = min(minn, arr[i]); 
        }
        for(int i = belong[l] + 1;i < belong[r]; ++i) minn = min(minn, minv[i]);           //中间部分直接查询
        return minn;
    }
}T;   
int main(){
    //freopen("input.in","r",stdin);
    T.build();
    while(m--){
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d ", T.query(a,b));
    }
    return 0;
}

  

 

原文地址:https://www.cnblogs.com/guangheli/p/9845093.html