[BZOJ 2809][Apio2012]dispatching:可持久化线段树|可并堆
来源:互联网 发布:刘雨欣张檬事件知乎 编辑:程序博客网 时间:2024/05/17 04:12
点击这里查看原题
对于每个忍者被作为管理者的情况,我们需要知道这个忍者管理的忍者中最多能选多少忍者,而要使选的忍者尽可能多,就需要从薪水最低的忍者开始选。
于是可以建立一颗权值线段树,按DFS序将忍者的薪水依次加入,每次求总薪水小于等于k可以选多少忍者。
注意long long,因为这个WA了好几次
/*User:SmallLanguage:C++Problem No.:2809*/#include<bits/stdc++.h>#define ll long longusing namespace std;const int M=1e5+5;int n,rt[M],tot,fir[M],cnt,in[M],out[M],dfn,a[M],p[M],id[M],pos[M],ls[M*20],rs[M*20],val[M];ll sum[M*20],sz[M*20],ans,k,b[M];struct edge{ int v,nex;}e[M<<1];void add(int u,int v){ e[++tot]=(edge){v,fir[u]}; fir[u]=tot;}bool cmp(int x,int y){ return a[x]<a[y];}void dfs(int u){ in[u]=++dfn; id[dfn]=pos[u]; val[dfn]=a[u]; for(int i=fir[u];i;i=e[i].nex) dfs(e[i].v); out[u]=dfn;}void build(int &now,int l,int r,int x,int v){ cnt++; sum[cnt]=(ll)sum[now]+(ll)v; sz[cnt]=sz[now]+1; ls[cnt]=ls[now]; rs[cnt]=rs[now]; now=cnt; if(l==r) return; int mid=l+r>>1; if(x<=mid) build(ls[now],l,mid,x,v); else build(rs[now],mid+1,r,x,v);}ll query(int a,int b,int l,int r,ll k,ll c){ int mid=l+r>>1; if(l==r){ if(sum[b]-sum[a]<=k&&sum[b]-sum[a]) return c+1; else return c; } ll t=sum[ls[b]]-sum[ls[a]]; if(t>=k) return query(ls[a],ls[b],l,mid,k,c); else{ return query(rs[a],rs[b],mid+1,r,k-t,c+sz[ls[b]]-sz[ls[a]]); }}int main(){ freopen("data.in","r",stdin);// scanf("%d%lld",&n,&k); for(int i=1;i<=n;i++){ int fa; scanf("%d%d%lld",&fa,&a[i],&b[i]); if(fa) add(fa,i); p[i]=i; } sort(p+1,p+n+1,cmp); for(int i=1;i<=n;i++) pos[p[i]]=i; dfs(1); for(int i=1;i<=n;i++){ rt[i]=rt[i-1]; build(rt[i],1,n,id[i],val[i]); } for(int i=1;i<=n;i++){ ll res=query(rt[in[i]-1],rt[out[i]],1,n,k,0); ans=max(ans,(ll)res*b[i]); } printf("%lld\n",ans); return 0;}
另一种做法是可并堆,维护最大堆,每当堆中的元素和大于总薪水时删除最大元素。
/*User:SmallLanguage:C++Problem No.:2809*/#include<bits/stdc++.h>#define ll long longusing namespace std;const int M=1e5+5;ll n,tot,fir[M],siz[M],rt[M];ll m,sum[M],b[M],ans,a[M];struct edge{ ll v,nex;}e[M<<1];struct no{ ll l,r; ll v;}tr[M<<2];void add(ll u,ll v){ e[++tot]=(edge){v,fir[u]}; fir[u]=tot;}ll merge(ll a,ll b){ if(!a||!b) return a+b; if(tr[a].v<tr[b].v) swap(a,b); tr[a].r=merge(tr[a].r,b); swap(tr[a].l,tr[a].r); return a;}void pop(ll x){ ll root=rt[x]; rt[x]=merge(tr[root].l,tr[root].r); sum[x]-=tr[root].v; siz[x]--; tr[root].l=tr[root].r=tr[root].v=0;}void dfs(ll u){ for(ll i=fir[u];i;i=e[i].nex){ ll v=e[i].v; dfs(v); sum[u]+=sum[v]; siz[u]+=siz[v]; rt[u]=merge(rt[u],rt[v]); while(sum[u]>m) pop(u); } sum[u]+=a[u]; siz[u]++; tr[u]=(no){0,0,a[u]}; rt[u]=merge(rt[u],u); while(sum[u]>m) pop(u); ans=max(ans,(ll)siz[u]*b[u]);}int main(){ freopen("data.in","r",stdin);// scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++){ ll fa; scanf("%lld%lld%lld",&fa,&a[i],&b[i]); if(fa) add(fa,i); } dfs(1); printf("%lld\n",ans); return 0;}
0 0
- [BZOJ 2809][Apio2012]dispatching:可持久化线段树|可并堆
- BZOJ 2809 [Apio2012]dispatching 可并堆
- [可并堆] BZOJ 2809 [Apio2012]dispatching
- 【BZOJ 2809】[Apio2012]dispatching 可并堆
- BZOJ 2809: [Apio2012]dispatching 可并堆
- BZOJ 2809 Apio2012]dispatching 斜堆 可并堆
- BZOJ 2809 APIO2012 dispatching Treap+启发式合并 / 可并堆
- bzoj 2809: [Apio2012]dispatching(可并堆)
- BZOJ 2809 [Apio2012]dispatching【可并堆(贪心
- BZOJ 2809: [Apio2012]dispatching 左偏树(可合并堆)
- [BZOJ2809] [APIO2012] dispatching - 可并堆
- [BZOJ2809][Apio2012]dispatching(可并堆)
- 可并堆-bzoj2809: [Apio2012]dispatching
- bzoj2809 [Apio2012]dispatching(可并堆)
- 2809: [Apio2012]dispatching 启发式合并treap 可并堆
- [Apio2012]dispatching 可合并堆 斜堆
- [BZOJ2809][Apio2012]dispatching(枚举&dfs序+主席树||可并堆||splay+启发式合并)
- [BZOJ]2809: [Apio2012]dispatching 主席树(线段树合并)
- ZeroMQ初探
- 基于JFinal建立的Db+Record实现的数据库表字段加密
- UIViewContentMode各类型效果
- 有关素数
- vim编辑器的使用
- [BZOJ 2809][Apio2012]dispatching:可持久化线段树|可并堆
- 数据结构---双向链表实现队列与循环链表
- EXCEL文件显示:您尝试打开的文件的格式与文件扩展名指定的格式不一致,打开前请验证文件示被损坏且来源可
- 隐私权政策说明
- Hadoop YARN介绍
- elasticsearch5.3集群 java 调用实例
- thinkphp链接pgsql
- Android之常见图标尺寸
- Jenkins进阶系列之——02email-ext邮件通知模板