【BZOJ2809】【codevs1763】派遣,主席树记录前缀和
来源:互联网 发布:网络侵犯名誉权案例 编辑:程序博客网 时间:2024/04/28 20:31
传送门1
传送门2
写在前面:祝自己生日快乐
思路:
题意简述为在一棵节点有特征值有费用的有根树上选定一个节点,在它的子树上找任意个节点使其总费用不超过m,要求权值最大(权值=该节点的特征值*选择的节点数)
比较暴力的思路是枚举每一个节点,从它的子树上依次选取费用从小到大的节点,直到超过费用或子树上全部节点都被选了,求出最大值即可,时间复杂度
将该思路精进一下,我们发现只要维护每个子树上的点费用从小到大,再加一个前缀和之类的东西,快速判断某一区间费用和是否超过费用即可就可以了
这就用到了主席树
这里的主席树不再是求区间第k大,因为它是权值线段树,节点即是费用(离散化后),所以在主席树上维护下前缀和,每次查询时判断[l,mid]是否超过限制,如果没有就加上左区间的点数,并到[mid+1,r]上去找,不然就继续到[l,mid]上找,每次查询的复杂度为
注意:
1.维护树上区间使用dfs序重新编号
2.离散化后的值仅是为了在主席树上使其有序,建树和查询时要用到的除了size还有费用前缀和sum
代码:
#include<bits/stdc++.h>#define M 100004#define LL long longusing namespace std;int n,m,cnt,root,tot;LL ans;int fa[M],b[2][M],c[M],ID[M],first[M],Ls[M],Rs[M];//b[0]为离散化前的费用,b[1]为离散化后的费用,ID[i]记录离散化后为i的原费用struct Chairman_tree{ int ch[2],siz; LL sum;}a[M<<5];struct disc{ int id,data; bool operator <(const disc other)const { return data<other.data; }}d[M];struct edge{ int u,v,next; void add(int x,int y) { u=x;v=y; next=first[x]; first[x]=tot; }}e[M];int in(){ char ch=getchar();int t=0; while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar(); return t;}void dfs(int x){ Ls[x]=++cnt; d[cnt].id=x;d[cnt].data=b[1][x]; for (int i=first[x];i;i=e[i].next) dfs(e[i].v); Rs[x]=cnt;}void build(int now,int L,int R,int rt,int val){ a[rt].siz=a[now].siz+1; a[rt].sum=a[now].sum+ID[val]; if (L==R) return; int mid=(L+R)>>1; if (val<=mid) a[rt].ch[1]=a[now].ch[1], a[rt].ch[0]=++cnt, build(a[now].ch[0],L,mid,a[rt].ch[0],val); else a[rt].ch[0]=a[now].ch[0], a[rt].ch[1]=++cnt, build(a[now].ch[1],mid+1,R,a[rt].ch[1],val);}int get(int begin,int end,int L,int R,LL val){ if (begin==end) if (ID[end]<=val) return a[R].siz-a[L].siz; else return 0; int mid=(begin+end)>>1; LL t=a[a[R].ch[0]].sum-a[a[L].ch[0]].sum; if (val>t) return a[a[R].ch[0]].siz-a[a[L].ch[0]].siz+get(mid+1,end,a[L].ch[1],a[R].ch[1],val-t); else return get(begin,mid,a[L].ch[0],a[R].ch[0],val);}main(){ n=in();m=in(); for (int i=1;i<=n;i++) { fa[i]=in(); if (fa[i]) e[++tot].add(fa[i],i); else root=i; b[0][i]=in(), d[i].id=i,d[i].data=b[0][i]; c[i]=in(); } sort(d+1,d+n+1); for (int i=1;i<=n;i++) b[1][d[i].id]=i, ID[i]=b[0][d[i].id]; dfs(root); cnt++; for (int i=1;i<=n;i++) build(i,1,n,i+1,d[i].data); for (int i=1;i<=n;i++) ans=max(ans,(LL)c[i]*get(1,n,Ls[i],Rs[i]+1,m)); printf("%lld",ans);}
0 0
- 【BZOJ2809】【codevs1763】派遣,主席树记录前缀和
- Bzoj2809 APIO2012 派遣 主席树经典题
- bzoj2809 [ APIO2012 ] -- 主席树
- 【APIO2012】【BZOJ2809】派遣dispatching
- bzoj2809 apio2012 派遣
- 【左偏堆】bzoj2809派遣
- 【bzoj2809】【APIO2010】派遣
- 【bzoj2809】[Apio2012]dispatching 主席树+dfs序
- 【bzoj2809】dispatching 主席树+dfs序
- [dfs序+主席树] BZOJ2809: [Apio2012]dispatching
- [BZOJ2809][Apio2012]dispatching(dfs序+主席树)
- 主席树学习记录
- [BZOJ2809][Apio2012]dispatching(枚举&dfs序+主席树||可并堆||splay+启发式合并)
- bzoj4408 [Fjoi 2016]神秘数(主席树维护前缀和)
- 学习记录5:主席树
- BZOJ2809
- bzoj2809
- BZOJ2809
- Android 判断应用是否在运行
- 数据结构与算法:C++实现插入排序
- [综合]visio2013安装提示找不到Office.zh_cn\officeMUI.mis officemui.xml
- LeetCode 32. Longest Valid Parentheses
- 写论文第八天:MATLAB之leadlagFun函数
- 【BZOJ2809】【codevs1763】派遣,主席树记录前缀和
- PHP自学no00003PHP注释
- 通过rsync+inotify-tools+ssh实现触发式远程实时同步
- 字节码文件初探
- 解决FF下不能使用outerHTML的2种方法
- [Util] can not load library from so file +++ register push fail. token:null, errCode:10004,msg:COD
- angularjs+ionic高大上的webApp(环境配置篇)
- PHP自学no00004数据类型布尔型真假
- NSURLRequest官方