洛谷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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值