該題題義是給定一個公司的結構,然後針對每個員工的一系列操作。由於問題牽涉到一個員工以及一個員工所領導的部門,因此用普通線性結構顯然效率太低。這裡用到了線段樹。
step1:首先我們要確定題目是要對給定的點或者是區間進行操作,那麼我們自然而然會想到線段樹,但是這題還不是直接的線段樹,需要對題中給定的關係進行離散話,也就是按
照先序或者是後序遍曆進行排序,這樣某一個員工所領導的部門下的成員就在物理上連續了,並且我們用兩個數組分別記錄某個成員所領導的部門的左邊界和右邊界。
step2:有了上一步的操作後,我們就可以進行構樹了,按照普通的線段樹進行構建,線段樹僅僅只是我們處理點和區間的一種資料結構,其本身沒有什麼實際意義,記得用一個映
射將線段樹的點和實際員工的編號聯絡起來,這樣方便了初始化,也便於最後的輸出。
step3:此時我們就可以來處理資料中所給定的操作了,點更新和區間更新,當然這裡可以用到lazy標記。
PS:由於整個數很可能退化成鏈表,所以最好使用非遞迴來實現先序或者是後序遍曆。
代碼如下:
#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#define MAXN 50005using namespace std;int N, Q, s[MAXN], stk[MAXN], visit[MAXN], top;int seq[MAXN], idx, L[MAXN], R[MAXN];typedef long long int Int64;queue<int>q[50005];struct Node{ int l, r; Int64 sum, lazy;}e[200005];void getseq(int boss) { int pos; idx = -1; top = 1; stk[top] = boss; memset(visit, 0, sizeof (visit)); while (top) { pos = stk[top]; if (!visit[pos]) { visit[pos] = 1; seq[++idx] = pos; L[pos] = idx; } if (!q[pos].empty()) { stk[++top] = q[pos].front(); q[pos].pop(); } else { R[pos] = idx; --top; } }}void build(int p, int l, int r){ e[p].l = l, e[p].r = r; e[p].lazy = 0; if (l!= r) { int mid = (l + r) >> 1; build(p<<1, l, mid); build(p<<1|1, mid+1, r); e[p].sum = e[p<<1].sum + e[p<<1|1].sum; } else { // l == r e[p].sum = s[seq[l]]; }}inline void update(int p){ e[p].sum = e[p<<1].sum + e[p<<1|1].sum;}Int64 sum(int p, int l, int r){ if (e[p].l == l && r == e[p].r) { return e[p].sum; } int mid = (e[p].l + e[p].r) >> 1; if (e[p].lazy) { e[p<<1].lazy += e[p].lazy; e[p<<1|1].lazy += e[p].lazy; e[p<<1].sum += (e[p<<1].r-e[p<<1].l+1)*e[p].lazy; e[p<<1|1].sum += (e[p<<1|1].r-e[p<<1|1].l+1)*e[p].lazy; e[p].lazy = 0; } if (r <= mid) { return sum(p<<1, l, r); } else if (l > mid) { return sum(p<<1|1, l, r); } else { return sum(p<<1, l, mid) + sum(p<<1|1, mid+1, r); }}void modify(int p, int l, int r, Int64 x){ if (e[p].l == l && r == e[p].r) { e[p].lazy += x; e[p].sum += (e[p].r-e[p].l+1) * x; // 身上有延時標記,但是本身的值一定要是正確的 return; } int mid = (e[p].l + e[p].r) >> 1; if (e[p].lazy) { e[p<<1].lazy += e[p].lazy; e[p<<1|1].lazy += e[p].lazy; e[p<<1].sum += (e[p<<1].r-e[p<<1].l+1)*e[p].lazy; e[p<<1|1].sum += (e[p<<1|1].r-e[p<<1|1].l+1)*e[p].lazy; e[p].lazy = 0; } if (r <= mid) { modify(p<<1, l, r, x); } else if (l > mid) { modify(p<<1|1, l, r, x); } else { modify(p<<1, l, mid, x); modify(p<<1|1, mid+1, r, x); } update(p);}int main(){ int p, x, y, z, first = 1; Int64 level; char op[15]; while (scanf("%d %d %d", &N, &Q, &s[0]), N|Q|s[0]) { if (first) { first = 0; } else { puts(""); } for (int i = 1; i < N; ++i) { scanf("%d %d", &p, &s[i]); q[p].push(i); } getseq(0); build(1, 0, N-1); // 區間劃分是 0 - N-1 while (Q--) { scanf("%s %d %d %d", op, &x, &y, &z); if (op[0] == 'e') { level = sum(1, L[x], L[x]); if (level < y) { modify(1, L[x], L[x], z); } } else { level = sum(1, L[x], R[x]); if (1.*level/((R[x]-L[x]+1)) < y) { modify(1, L[x], R[x], z); } } } for (int i = 0; i < N; ++i) { printf("%lld\n", sum(1, L[i], L[i])); } } return 0;}