牛客小白月赛12 H华华和月月种树 (离线dfs序+线段树)
鏈接:https://ac.nowcoder.com/acm/contest/392/H
來源:牛客網
時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
題目描述
華華看書了解到,一起玩養成類的游戲有助于兩人培養感情。所以他決定和月月一起種一棵樹。因為華華現在也是信息學高手了,所以他們種的樹是信息學意義下的。
華華和月月一起維護了一棵動態有根樹,每個點有一個權值。剛開存檔的時候,樹上只有 0 號節點,權值為 0 。接下來有兩種操作:
操作 1:輸入格式1?i1 i,表示月月氪金使節點 i 長出了一個新的兒子節點,權值為0,編號為當前最大編號 +1(也可以理解為,當前是第幾個操作 1,新節點的編號就是多少)。
操作 2:輸入格式 2 ?i ?a2 i a,表示華華上線做任務使節點 i 的子樹中所有節點(即它和它的所有子孫節點)權值加 a 。
但是月月有時會檢查華華有沒有認真維護這棵樹,會作出詢問:
詢問 3:輸入格式3?i3 i,華華需要給出 i 節點此時的權值。
華華當然有認真種樹了,不過還是希望能寫個程序以備不時之需。
輸入描述:
第一行一個正整數M,接下來M行,每行先輸入一個正整數O表示操作類型,再輸入一個非負整數i表示操作或詢問的節點編號,如果O=2,再輸入一個正整數a。
輸出描述:
對于每個詢問3,輸出一個非負整數表示詢問的答案。
示例1
輸入
復制
9
1 0
2 0 1
3 0
3 1
1 0
1 1
2 0 2
3 1
3 3
輸出
復制
1
1
3
2
備注:
1\le M\le 4\times 10^51≤M≤4×10
5
,保證操作1的數量不超過10^510
5
,保證操作2中的參數a滿足1\le a\le 9991≤a≤999
思路:
先按照題目把每個節點建立出來,形成一個完整的樹,
然后dfs遍歷樹得到dfn序,同時維護出以節點i為根的子樹節點個數cntson[i],然后根據dfn序列的性質一個節點i為根的子樹是一個連續的序列,且序列長度為cntson[i]
,所以建立線段樹來維護整個數的節點值,
我們從1~m以此離線處理命令,對于每一個加節點的過程,我們把這個節點的權值清零就可以消除掉建立這個節點之前的操作對這個節點的權值影響。
細節見代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 400010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ struct node1 {int op;int x;int y; } info[maxn]; int m; std::vector<int> son[maxn]; int n = 1; int id[maxn]; int cnt = 0; int cntson[maxn]; void dfs(int x, int pre) {cntson[x] = 1;id[x] = ++cnt;for (auto y : son[x]){if (y != pre){dfs(y, x);cntson[x] += cntson[y];}} } struct node {int l, r;ll sum;ll laze; } segment_tree[maxn << 2]; void pushup(int rt) {segment_tree[rt].sum = segment_tree[rt << 1].sum + segment_tree[rt << 1 | 1].sum; } void pushdown(int rt) {if (segment_tree[rt].laze){ll num = segment_tree[rt].laze;segment_tree[rt << 1 | 1].laze += num;segment_tree[rt << 1].laze += num;segment_tree[rt << 1 | 1].sum += num * (segment_tree[rt << 1 | 1].r - segment_tree[rt << 1 | 1].l + 1);segment_tree[rt << 1].sum += num * (segment_tree[rt << 1].r - segment_tree[rt << 1].l + 1);segment_tree[rt].laze = 0ll;} } void build(int rt, int l, int r) {segment_tree[rt].l = l;segment_tree[rt].r = r;if (l == r){segment_tree[rt].sum = 0;segment_tree[rt].laze = 0;return ;}int mid = (r + l) >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushup(rt); } void change(int rt, int l, int r, ll val) {pushdown(rt);if (segment_tree[rt].l == l && segment_tree[rt].r == r && l == r){segment_tree[rt].sum = 0;return ;}int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;if (l <= mid){change(rt << 1, l, r, val);}if (r >= mid + 1){change(rt << 1 | 1, l, r, val);}pushup(rt); } void update(int rt, int l, int r, ll val) {pushdown(rt);if (l <= segment_tree[rt].l && segment_tree[rt].r <= r ){segment_tree[rt].sum += 1ll * (segment_tree[rt].r - segment_tree[rt].l + 1) * val;segment_tree[rt].laze += val;return ;}int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;if (l <= mid){update(rt << 1, l, r, val);}if (r >= mid + 1){update(rt << 1 | 1, l , r, val);}pushup(rt); } ll query(int rt, int l, int r) {pushdown(rt);if (segment_tree[rt].l == l && segment_tree[rt].r == r){return segment_tree[rt].sum;}int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;ll res = 0ll;if (mid >= l){res += query(rt << 1, l, r);}if (r >= mid + 1){res += query(rt << 1 | 1, l, r);}return res; } int main() {//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);scanf("%d", &m);repd(i, 1, m){scanf("%d %d", &info[i].op, &info[i].x); info[i].x++;if (info[i].op == 2){scanf("%d", &info[i].y);} else if (info[i].op == 1){son[info[i].x].push_back(++n);info[i].y = n;}}dfs(1, -1);int now = 2;build(1, 1, n);repd(i, 1, m){if (info[i].op == 1){change(1, id[now], id[now], 0);now++;} else if (info[i].op == 3){printf("%lld\n", query(1, id[info[i].x], id[info[i].x]) );} else{update(1, id[info[i].x], id[info[i].x] + cntson[info[i].x] - 1, info[i].y);}}return 0; }inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}}else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}} }轉載于:https://www.cnblogs.com/qieqiemin/p/11424480.html
總結
以上是生活随笔為你收集整理的牛客小白月赛12 H华华和月月种树 (离线dfs序+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《上邪》诗解
- 下一篇: 铁血规则:事件预订与取消预订