博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2809 [Apio2012]dispatching
阅读量:5766 次
发布时间:2019-06-18

本文共 2409 字,大约阅读时间需要 8 分钟。

题目链接

思路

显然,选取需要工资最少的几个人最优。

枚举领导者的编号,问题就变成了求每个点的子树中工资kk能满足多少员工了。

很容易想到使用可并堆,如果选择建立小根堆会TLE,正解是选择建立大根堆,每次从这个点的子树中踢出需要工资最大的员工,如果被一个点的子节点踢出了,那么这个节点显然不会选择他。一步一步向上合并就可以A了。

代码

#include 
#include
const int maxn=100000;int read(){ int x=0,f=1; char ch=getchar(); while((ch<'0')||(ch>'9')) { if(ch=='-') { f=-f; } ch=getchar(); } while((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f;}struct node{ node* son[2]; node* fa; int val,dist;};node tnode[maxn+10];node* root[maxn+10];int n,m,cnt,nump[maxn+10],c[maxn+10],l[maxn+10];long long giv[maxn+10],ans;int pre[maxn+10],now[maxn+10],son[maxn+10],tot;inline int upd_dist(node* now){ if(now->son[1]==NULL) { now->dist=0; } else { now->dist=now->son[1]->dist+1; } return 0;}node* merge(node* a,node* b){ if(a==NULL) { return b; } if(b==NULL) { return a; } if(a->val
val) { std::swap(a,b); } a->son[1]=merge(a->son[1],b); if(a->son[1]!=NULL) { a->son[1]->fa=a; } if((a->son[0]!=NULL)&&(a->son[1]!=NULL)&&(a->son[0]->dist
son[1]->dist)) { std::swap(a->son[0],a->son[1]); } else if((a->son[0]==NULL)&&(a->son[1]!=NULL)) { a->son[0]=a->son[1]; a->son[1]=NULL; } upd_dist(a); return a;}node* getf(node* now){ if(now->fa==NULL) { return now; } return getf(now->fa);}inline int getmax(node* x){ return getf(x)->val;}inline node* pop(node* x){ node* f=getf(x); node* s=merge(f->son[0],f->son[1]); s->fa=NULL; return s;}inline int ins(int a,int b){ pre[++tot]=now[a]; now[a]=tot; son[tot]=b; return 0;}int dfs(int u){ root[u]=&tnode[++cnt]; root[u]->fa=root[u]->son[0]=root[u]->son[1]=NULL; root[u]->val=c[u]; root[u]->dist=0; giv[u]=c[u]; nump[u]=1; int j=now[u]; while(j) { int v=son[j]; dfs(v); root[u]=merge(root[u],root[v]); giv[u]+=giv[v]; nump[u]+=nump[v]; j=pre[j]; } while(giv[u]>m) { giv[u]-=getmax(root[u]); --nump[u]; root[u]=pop(root[u]); } ans=std::max(ans,1ll*l[u]*nump[u]); return 0;}int main(){ n=read(); m=read(); for(int i=1; i<=n; ++i) { int f=read(); ins(f,i); c[i]=read(); l[i]=read(); } dfs(1); printf("%lld\n",ans); return 0;}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376166.html

你可能感兴趣的文章
ChPlayer播放器的使用
查看>>
js 经过修改改良的全浏览器支持的软键盘,随机排列
查看>>
Mysql读写分离
查看>>
Oracle 备份与恢复学习笔记(5_1)
查看>>
Oracle 备份与恢复学习笔记(14)
查看>>
分布式配置中心disconf第一部(基本介绍)
查看>>
Scenario 9-Shared Uplink Set with Active/Active uplink,802.3ad(LACP)-Flex-10
查看>>
UML类图中的六种关系
查看>>
探寻Interpolator源码,自定义插值器
查看>>
一致性哈希
查看>>
mysql(待整理)
查看>>
看雪论坛502,出现安全宝?
查看>>
使用PullToRefresh实现下拉刷新和上拉加载
查看>>
mysql
查看>>
2012年电信业八大发展趋势
查看>>
Web日志安全分析工具 v2.0发布
查看>>
JS重载
查看>>
python2和python3同安装在Windows上,切换问题
查看>>
php加速工具xcache的安装与使用(基于LNMP环境)
查看>>
android超链接
查看>>