HDU1754 I Hate It(树状数组 or 线段树)

题目链接

分析:

本题可以用树状数组,也可以用线段树。

树状数组:

对于树状数组,请详见本随笔

 

要注意的是,比如说上图,要求 2 到 4 之间的最大值, c[4] 并非 2 到 4 之间的最大值,因为 c[4] 是 1 到 4 之间的最大值。这时候就只能单独看A[4], A[3], A[2]了。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

const int maxn = 200000 + 10;
int num[maxn], c[maxn], n, m;

int lowbit(int t){
    return t & (-t);
}

void add(int x, int d){
    num[x] = d;
    while(x <= n){
        if(c[x] < d){
            c[x] = d;
        }
        else break;
        x = x + lowbit(x);
    }
}

int get_max(int l, int r){
    int ans = num[r];
    while(l != r){
        r--;//这里也注意下
        while(r - lowbit(r) > l){   //这里注意下
            ans = max(ans, c[r]);
            r -= lowbit(r);
        }
        ans = max(ans, num[r]);
    }
    return ans;
}

int main(){
    int a, b;
    char ch[2];
    while(scanf("%d%d", &n, &m) == 2){
        memset(num, 0, sizeof(num));
        memset(c, 0, sizeof(c));
        for(int i=1; i<=n; i++){
            scanf("%d", &a);
            add(i, a);
        }
        for(int i=0; i<m; i++){
            scanf("%s%d%d", ch, &a, &b);
            if(ch[0] == 'Q'){
                printf("%d\n", get_max(a, b));
            }
            else{
                add(a, b);
            }
        }
    }

    return 0;
}
View Code

 

 

线段树:

 

#include <cstdio>
#include <cmath>
#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

const int maxn = 200000+10;

struct Node {
    int left;
    int right;
    int max;
}node[maxn*4];

int a[maxn];

void build(int l, int r, int i) {
    node[i].left = l;
    node[i].right = r;

    if(l == r) {
        node[i].max = a[l];
        return ;
    }

    int mid = (l+r)/2;
    build(l, mid, i*2);
    build(mid+1, r, i*2+1);
    node[i].max = max(node[i*2].max, node[i*2+1].max);
}

void Update(int id, int value, int i) {
    if(node[i].left == node[i].right) {
        node[i].max = value;
        return ;
    }

    int mid = (node[i].left + node[i].right)/2;
    if(id <= mid) Update(id, value, i*2); //要用 <=
    else Update(id, value, 2*i+1);

    node[i].max = max(node[i*2].max, node[i*2+1].max);
}

int Query(int l, int r, int i) {
    if(node[i].left == l && node[i].right == r) return node[i].max;
    else {
        int mid = (node[i].left + node[i].right)/2;
        int ans = -1;

        if(l <= node[i].left && node[i].right <= r) return node[i].max;
        if(l <= mid) ans = max(ans, Query(l, r, i*2));
        if(mid < r) ans = max(ans, Query(l, r, i*2+1));
        return ans;

        //else里的这一小部分也可以这样写
        /*
        if(mid >= r) return Query(l, r, 2*i);
        else if(mid < l) return Query(l, r, 2*i+1);
        else {
            int ans = -1;
            ans = max(ans, Query(l, mid, 2*i));
            ans = max(ans, Query(mid+1, r, 2*i+1));
            return ans;
        }*/
    }
}

int main(){
    int n, m;
    while(scanf("%d%d", &n, &m) == 2) {
        for(int i=1; i<=n; i++) scanf("%d", &a[i]);

        build(1, n, 1);

        char s[2];
        int x, y;

        for(int i=0; i<m; i++) {
            scanf("%s %d%d", s, &x, &y);
            if(s[0] == 'Q') printf("%d\n", Query(x, y , 1));
            else Update(x, y, 1);
        }
    }

    return 0;
}
View Code

 

 

 

 

 

 

 

 

 

posted on 2013-05-03 09:46  Still_Raining  阅读(204)  评论(0编辑  收藏  举报