6.Bzoj2809 [Apio2012]dispatching (左偏樹
阿新 • • 發佈:2018-11-27
剛開始怎麼都不會做.如果M比較小,還可以用樹形動態做
後來才發現讀錯題目了
然後就是一個比較容易的左偏樹題目
然後貪心的考慮,肯定把小值選上,直到總和 <= M且不能再加剩下的
首先考慮每一個點作為管理者的貢獻
然後繼續貪心的考慮
一次次彈出最大值
直到裡面的和 <= M是最優的
左偏樹維護一下即可.
可是好難寫啊。。。。。。。
維護好多東西啊....
維護左偏樹的和,左偏樹結點的個數
開了longlong,竟然一遍過了!!(震驚
//卡常記錄 535ms -> 480ms #include <iostream> #include <cstdio> #define rep(i , x, p) for(register int i = x;i <= p;++ i) #define sep(i , x, p) for(int i = x;i >= p;-- i) #define gc getchar() #define pc putchar #define ll long long inline int read() {int x = 0,f = 1;char c = gc;while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;} void print(int x) {if(x < 0) pc('-') , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + '0');} using std::swap; using std::max; using std::min; const int maxN = 100000 + 7; int size[maxN] , M, n, w[maxN];; ll sum[maxN]; //f表示這個點最多可以選擇多少個點. //sum表示堆裡元素的和. //w表示管理值 struct Node { int lson , rson, key, dis; }P[maxN]; struct Edge { int v , nex; }Map[maxN]; int head[maxN] , num; void add_Node(int u,int v) { Map[++ num] = (Edge) {v , head[u]}; head[u] = num; return ; } int Merge(int x,int y) { if(!x || !y) return x + y; if(P[x].key < P[y].key) swap(x , y); P[x].rson = Merge(P[x].rson , y); if(P[P[x].rson].dis > P[P[x].lson].dis) swap(P[x].lson , P[x].rson); P[x].dis = P[P[x].rson].dis + 1; return x; } inline int Dele(int x) {return Merge(P[x].lson , P[x].rson);} int dfs(int now) { int top = now , tmp_size = 1; ll tmp_sum = P[now].key; for(int i = head[now];i;i = Map[i].nex) { int v = Map[i].v; int q = Merge(top , dfs(v)); tmp_sum += sum[v]; tmp_size += size[v]; top = q; } while(tmp_sum > M) { tmp_sum -= P[top].key; int q = Dele(top);tmp_size --; top = q; } sum[now] = tmp_sum; size[now] = tmp_size; return top; } int main() { n = read();M = read(); int B , C, L; rep(i , 1, n) { B = read(); add_Node(B , i); P[i].key = read(); w[i] = read(); } dfs(1); ll ans = 0; rep(i , 1, n) ans = max((ll)size[i] * w[i] , ans); printf("%lld",ans); return 0; }