HDU - 1754 I Hate It 分块入门(分块思想)

题意:

给定一段序列,更新某个点的值,查询某个区间的最大值;

思路:

首先,这个题的很好的做法应该是线段树,线段树是维护区间最值的很好的数据结构,

这里作为分块算法的入门题,学习一下;

分块 听说很牛逼,还有分块的思想也是很好的,是把问题根据某个条件分割,然后对某一部分进行暴力;  有点类似于哈希

对于这个题,更新和查询的复杂度都是 sqrt() 级别的,


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 7, maxd = 500 + 7, mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;

int n, m, q;
char s[3];
int a[maxn], id[maxn], max_[maxd];

void updata(int pos, int x) {
    a[pos] = x;
    int t = id[pos];
    for(int i = (t-1)*m+1; i <= t*m; ++i)
        max_[t] = max( max_[t], x );
}

int query(int l_, int r_) {
    int ans = 0;
    if(id[l_] == id[r_]) {
        for(int i = l_; i <= r_; ++i)
            ans = max( ans, a[i]);
    }
    else {
        int t1 = id[l_]*m, t2 = (id[r_]-1)*m+1;
        for(int i = l_; i <= t1; ++i)
            ans = max( ans, a[i]);
        for(int i = t2; i <= r_; ++i)
            ans = max( ans, a[i]);
        for(int i = id[l_]+1; i < id[r_]; ++i)
            ans = max( ans, max_[i]);
    }
    return ans;
}

void init() {
    memset(max_, 0, sizeof max_);
    for(int i = 1; i <= n; ++i)
        id[i] = (i-1) / m + 1;
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= n; ++i) 
        max_[id[i]] = max( max_[id[i]], a[i]);
}

int main() {
    while(~scanf("%d %d", &n, &q) && n) {
        m = sqrt(n);
        init();
        for(int i = 0; i < q; ++i) {
            int x, y;
            scanf("%s %d %d", s, &x, &y);
            if(s[0] == 'Q') {
                printf("%d\n", query(x, y));
            }
            else updata(x, y);
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值