HDU 1754 I Hate It(線段數-單點更新)
阿新 • • 發佈:2018-12-24
原題連結:I Hate It
題目分析:這個是線段樹的基本操作——更新和查詢,屬於基礎題,也就相當於一個模板吧,這裡就不再多說了。
程式碼如下:
(PS:特別注意——輸入輸出用 不然會超時)
#include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int MAXNODE = 524288/*2097152*/; const int MAX = 200001/*1000003*/; struct NODE { int value; // 結點對應區間的權值 int left,right; // 區間 [left,right] } node[MAXNODE]; int father[MAX]; // 每個點(當區間長度為0時,對應一個點)對應的結構體陣列下標 void BuildTree(int i, int left, int right) { // 為區間[left,right]建立一個以i為祖先的線段樹,i為陣列下標,我稱作結點序號 node[i].left = left; // 寫入第i個結點中的 左區間 node[i].right = right; // 寫入第i個結點中的 右區間 node[i].value = 0; // 每個區間初始化為 0 if (left == right) { // 當區間長度為 0 時,結束遞迴 father[left] = i; // 能知道某個點對應的序號,為了更新的時候從下往上一直到頂 return; } // 該結點往 左孩子的方向 繼續建立線段樹,線段的劃分是二分思想,如果寫過二分查詢的話這裡很容易接受 // 這裡將 區間[left,right] 一分為二了 BuildTree(i << 1, left, (int)floor((right + left) / 2.0)); // 該結點往 右孩子的方向 繼續建立線段樹 BuildTree((i << 1) + 1, (int)floor((right + left) / 2.0) + 1, right); } void UpdataTree(int ri) { // 從下往上更新(注:這個點本身已經在函式外更新過了) if (ri == 1) return; // 向上已經找到了祖先(整個線段樹的祖先結點 對應的下標為1) int fi = ri / 2; // ri 的父結點 int a = node[fi << 1].value; // 該父結點的兩個孩子結點(左) int b = node[(fi << 1) + 1].value; // 右 node[fi].value = (a > b) ? (a) : (b); // 更新這個父結點(從兩個孩子結點中挑個大的) UpdataTree(ri / 2); // 遞迴更新,由父結點往上找 } int Max /*= -1 << 20*/; void Query(int i, int l, int r) { // i為區間的序號(對應的區間是最大範圍的那個區間,也是第一個圖最頂端的區間,一般初始是 1 啦) if (node[i].left == l && node[i].right == r) { // 找到了一個完全重合的區間 Max = (Max < node[i].value) ? node[i].value : (Max); return; } i = i << 1; // get the left child of the tree node if (l <= node[i].right) { // 左區間有涉及 if (r <= node[i].right) // 全包含於左區間,則查詢區間形態不變 Query(i, l, r); else // 半包含於左區間,則查詢區間拆分,左端點不變,右端點變為左孩子的右區間端點 Query(i, l, node[i].right); } i += 1; // right child of the tree if (r >= node[i].left) { // 右區間有涉及 if (l >= node[i].left) // 全包含於右區間,則查詢區間形態不變 Query(i, l, r); else // 半包含於左區間,則查詢區間拆分,與上同理 Query(i, node[i].left, r); } } int main() { int n, m, Value; while (scanf("%d %d", &n, &m) != EOF) { BuildTree(1, 1, n); for (int i = 1; i <= n; i++) { scanf("%d", &Value); node[father[i]].value = Value; // 底層的無條件更新成績 UpdataTree(father[i]); } while (m--) { char ch[2]; int a, b; scanf("%s %d %d", ch, &a, &b); if (ch[0] == 'Q') { Max = 0; Query(1, a, b); printf("%d\n", Max); } else { node[father[a]].value = b; // 底層的無條件更新成績 UpdataTree(father[a]); } } } return 0; }