BZOJ 2809 [Apio2012]dispatching【可并堆(贪心

来源:互联网 发布:java运行出现antbuild 编辑:程序博客网 时间:2024/04/30 04:10

开了很久的坑,显然对于每个节点,选择以它为根的最小的那几个最优,于是每个节点开一个大根堆,从叶子往上合并就好,如果不合法就弹掉最大的元素

#include<bits/stdc++.h>#define MAXN 100005using namespace std;int n,m;inline int read(){register char ch = getchar();while(!isdigit(ch))ch = getchar();int rtn = 0;while(isdigit(ch))rtn = rtn*10 + ch - '0' , ch = getchar();return rtn;}//============================================================struct Node{Node *Son,*Brother;int key,size;Node(){}Node(Node *Son,Node *Brother,int key,int size):Son(Son),Brother(Brother),key(key),size(size){}}ttt[MAXN],*root[MAXN],*null;int cnt_node;inline Node * New_node(Node *s,Node *b,int k,int ss){return &(ttt[++cnt_node] = Node(s,b,k,ss));}inline Node * merge(Node *a,Node *b){if(a==null)return b;if(b==null)return a;if(a->key<b->key)swap(a,b);a->Brother = 0;b->Brother = a->Son;a->Son = b;a->size += b->size;return a;}inline Node * pop(Node *a){queue<Node *> q;for(Node *now = a->Son;now!=null;now = now->Brother)q.push(now);while(q.size() > 1u){Node *a = q.front();q.pop();Node *b = q.front();q.pop();q.push(merge(a,b));}return q.front();}//============================================================struct t1{int to,nxt;}edge[MAXN<<1];int cnt_edge;int fst[MAXN];void addedge(int x,int y){edge[++cnt_edge].to = y;edge[cnt_edge].nxt = fst[x];fst[x] = cnt_edge;}int cst[MAXN],led[MAXN];long long sum[MAXN];long long ans = 0;void dfs(int now){sum[now] = cst[now];root[now] = New_node(null,null,cst[now],1);for(int tmp = fst[now];tmp;tmp=edge[tmp].nxt){int aim = edge[tmp].to;dfs(aim);root[now] = merge(root[aim],root[now]);sum[now] += sum[aim];while(sum[now] > m){sum[now] -= (root[now]->key);root[now] = pop(root[now]);}}ans = max(ans,(long long)led[now]*( root[now]->size ));}int main(){freopen("1.in","r",stdin);n = read(),m = read();for(int i=1;i<=n;++i){int f = read();addedge(f,i);cst[i] = read() , led[i] = read();}null = new Node(0,0,0,0);dfs(0);printf("%lld",ans);return 0;}


0 0