HDU-1166 敵兵佈陣 (裸線段樹演算法)
阿新 • • 發佈:2019-02-14
#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", ×); 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; }