HDU-1698 Just a Hook(線段樹)

題目大意:

dota2裏面有個英雄叫屠夫,屠夫有一個鉤子武器,武器上面有n個勾釘,一開始這些勾釘全部是用銅做的。後來規定屠夫可以對鉤子做m次修改,使得鉤子上一部分連續的勾釘改爲用銀子做的,或者是金子做的。
一個銅釘的價值是1
一個銀釘的價值是2
一個金釘的價值是3
請問在做m次變換後鉤子的總價值是多少。

算法分析:

這道題無疑使用線段樹做,我之前做了幾道線段樹的題,對線段樹已經有了一定的瞭解,可以在很快的時間裏面將線段樹模板敲出來。但是遇到這道題就抓瞎了。這道題相當靈活,不是簡單的敲個模板就能過去的,我一開始沒想清楚就開始做,結果就超時了,
後來還是稍微看了一下別人的代碼(雖然沒看懂,但是給了我很大的啓發),纔將這道題做出來的。
這道題的關鍵在於,每次改變都是改變的一塊連續的區域,如果對該塊區域沒個點進行更新操作的話,絕對超時(我第一次就是這樣超時的),正確方法是在樹節點上保存當前該塊連續區域使用哪種金屬材料製成的(1,2,3),假設是0的話,那就意味着當前連續區域的狀態是割裂的,並不是一致的金屬材料,這也意味這當前節點的左右節點肯定是已經經過更新的!這裏有一點動態規劃的感覺。
然後要注意的就是一些編程小技巧。


代碼實現:

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

#include <iostream>
#include <algorithm>

using namespace std;

struct node
{
    int type;
    int begin;
    int end;
    int sum;
} tree[440000];

int n, m;

void build(int root, int begin, int end)
{
    tree[root].begin = begin;
    tree[root].end = end;
    tree[root].type = 1;
    if (begin == end) {
        tree[root].sum = 1;
        return;
    }
    build(root << 1, begin, begin + (end-begin)/2);
    build(root << 1 | 1, begin + (end-begin)/2 + 1, end);
    tree[root].sum = tree[root << 1].sum + tree[root << 1 | 1].sum;
}

void update(int root, int front, int rear, int type)
{
    if (front == tree[root].begin && rear == tree[root].end) {
        tree[root].sum = type * (rear - front + 1);
        tree[root].type = type;
        return;
    }

    int middle = tree[root].begin + (tree[root].end-tree[root].begin) / 2;

    if (tree[root].type) {
        tree[root<<1].type = tree[root<<1|1].type = tree[root].type;
        // 這兩步相當重要,等於是把當前狀態向下延伸
        tree[root<<1].sum = tree[root].type * (middle-tree[root].begin+1);
        tree[root<<1|1].sum = tree[root].type * (tree[root].end-middle);
    }
    if (rear <= middle) {
        update(root << 1, front, rear, type);
    } else if (front > middle) {
        update(root << 1 | 1, front, rear, type);
    } else {
        update(root << 1, front, middle, type);
        update(root << 1 | 1, middle+1, rear, type);
    }
    tree[root].type = 0;
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
}

int main()
{
    int times;
    int x, y, z;

    scanf("%d", ×);

    for (int t = 1; t <= times; t++) {
        scanf("%d", &n);
        build(1, 1, n);
        scanf("%d", &m);
        for (int i = 1; i <= m; i++) {
            scanf("%d%d%d", &x, &y, &z);
            update(1, x, y, z);
//            printf("%d\n", tree[1].sum);
        }
        printf("Case %d: The total value of the hook is %d.\n", t, tree[1].sum);
    }

    return 0;
}


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