HDU-1166 敵兵佈陣 (裸線段樹算法)

題目大意:

這道題是中文題,也沒什麼好解釋的,就是查詢區間內的和,和更新區間內的值。


算法分析:

這道題用我之前接觸過的樹狀數組算法也能做(大概,我對樹狀數組不是很瞭解)。我去簡單瞭解了一下線段樹,大概就是說,將區間不斷一分爲二。
比如總共有n個數,第一個節點保存1~n的總值,左孩子保存1 ~ n/2+1區間內的總值,右孩子保存 n/2+1 ~ n 區間內的總值,如此不斷迭代下去。
這樣的話,無論是更新還是查詢,時間複雜度都爲logn。


代碼實現:

#include <stdio.h>
#include <string.h>

#include <iostream>
#include <algorithm>

using namespace std;

struct node
{
    int value;           // 區間開始
    int begin;           // 區間結束
    int end;
} tree[300000];

int n;
int pa[55000];          // 用於保存每個元素對應的葉子節點

int build(int root, int begin, int end)
{
    tree[root].begin = begin;
    tree[root].end = end;
    if (begin == end) {
        // 因爲總是從左孩子開始,所以可以把輸入放在初始化線段樹的步驟裏面
	scanf("%d", &tree[root].value);
        pa[begin] = root;
    } else {
        int left = build(root << 1, begin, begin+(end-begin)/2);
        int right = build(root << 1 | 1, begin+(end-begin)/2+1, end);
        tree[root].value = left + right;
    }
    return tree[root].value;
}

void update(int root, int add)
{
    tree[root].value += add;
    if (root != 1)
        update(root >> 1, add);
}

int query(int root, int front, int rear)
{
    if (front == tree[root].begin && rear == tree[root].end) {      // 函數出口
        return tree[root].value;
    } else if (front > tree[root].end || rear < tree[root].begin) {
        return 0;
    }

    int middle = tree[root].begin + (tree[root].end - tree[root].begin) / 2;        // 獲取當前範圍的終

    if (rear < middle) {
        return query(root << 1, front, rear);
    } else if (front > middle+1) {
        return query(root << 1 | 1, front, rear);
    } else {
        int left = query(root << 1, front, middle);
        int right = query(root << 1 | 1, middle+1, rear);
        return left + right;
    }
}

int main()
{
    int times, x, y, add;
    char command[100];

    scanf("%d", &times);
    for (int t = 1; t <= times; t++) {
        memset(tree, 0, sizeof(tree));
        scanf("%d", &n);
        tree[0].value = 0;
        build(1, 1, n);
        printf("Case %d:\n", t);
        while (scanf("%s", command), strcmp(command, "End")) {
            if (!strcmp(command, "Add")) {
                scanf("%d%d", &x, &add);
                update(pa[x], add);
            } else if (!strcmp(command, "Sub")) {
                scanf("%d%d", &x, &add);
                update(pa[x], -add);
            } else {
                scanf("%d%d", &x, &y);
                printf("%d\n", query(1, x, y));
            }
        }
    }

    return 0;
}


發佈了53 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章