【bzoj2809】派遣 (左偏树)
题目分析
每个节点都是一颗(大根堆)左偏树,先按bfs序存入数组,然后倒着从底层开始:如果当前节点的子树sum > m 那么就把根节点删去,然后统计更新答案,并将这棵树和父节点合并。
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int N = 2e5 + 5; int n, m, fa[N], c[N], l[N]; int ecnt, adj[N], go[N], nxt[N]; typedef long long ll; #define SZ(x) (x?x->sze:0) #define S(x) (x?x->sum:0) #define D(x) (x?x->dist:-1) struct node{ node *lc, *rc; int dist, sze, val; ll sum; node(){} node( int v):lc(NULL), rc(NULL), dist(0), sze(1), val(v), sum(v){} inline node* upt(){ sze = SZ(lc) + SZ(rc) + 1; sum = S(lc) + S(rc) + val; return this ; } }*tr[N]; int qn, que[N], root; ll ans; inline void addEdge( int u, int v){ nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v; } inline node* Merge(node *u, node *v){ if (!u) return v; if (!v) return u; if (u->val < v->val) swap(u, v); u->rc = Merge(u->rc, v); if (D(u->rc) > D(u->lc)) swap(u->lc, u->rc); u->dist = D(u->rc) + 1; return u->upt(); } inline void handle( int u){ while (tr[u]->sum > m) tr[u] = Merge(tr[u]->lc, tr[u]->rc); } inline void solve(){ que[qn = 1] = root; for ( int ql = 1; ql <= qn; ql++){ int u = que[ql]; for ( int e = adj[u]; e; e = nxt[e]) que[++qn] = go[e]; } for ( int ql = qn; ql >= 2; ql--){ int u = que[ql], f = fa[u]; handle(u); ans = max(ans, 1LL * tr[u]->sze * l[u]); tr[f] = Merge(tr[f], tr[u]); } handle(root); ans = max(ans, 1LL * tr[root]->sze * l[root]); } inline int read(){ int i = 0, f = 1; char ch = getchar (); for (; (ch < '0' || ch > '9' ) && ch != '-' ; ch = getchar ()); if (ch == '-' ) f = -1, ch = getchar (); for (; ch >= '0' && ch <= '9' ; ch = getchar ()) i = (i << 3) + (i << 1) + (ch - '0' ); return i * f; } inline void wr(ll x){ if (x < 0) putchar ( '-' ), x = -x; if (x > 9) wr(x / 10); putchar (x % 10 + '0' ); } int main(){ n = read(), m = read(); for ( int i = 1; i <= n; i++){ fa[i] = read(), c[i] = read(), l[i] = read(); tr[i] = new node(c[i]); if (fa[i] == 0) root = i; else addEdge(fa[i], i); } solve(); wr(ans); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步