JZOJ3501. 【NOIP2013模拟联考15】消息传递
来源:互联网 发布:淘宝生活服务类目 编辑:程序博客网 时间:2024/06/07 00:32
辣鸡题解
题目描述
给出一棵树,可以任意选择一个点作为起始点(消耗1时间)。在1单位时间内,每个上轮已访问过的点可以扩展一个节点,求最少花费时间和最少花费的起点。
20%
则
解释一下。
如果i有一些儿子要传,那么肯定先传该从儿子传下去时间大的,否则以后再传所需时间更长。
然后每个点都做一遍就可以20分了。
(25分?玄学)
话说我考试时要是交上去就有25分了
80% & 100%
官方的题解是说把一个点从作为根的父亲上移过去,使其成为新的根。
中途似乎要用到RMQ+二分之类的奇♂妙算法所以果断弃疗
咳咳
讲讲个人的奇♂妙算法。
20%的算法瓶颈在于要把每个点都算一遍,所以时间复杂度是
设
似乎不易理解实际比题解好理解多了
至于
每次从i的兄弟的F,还有i父亲的G中转移,具体类似F[i]的转移方式。
这样随便水一下能有80分
100分类似80分,只不过有些人工数据十分鬼畜,基本上是一个点连着剩下一片点,这样效率会退化到
然而解决方法也很简单,只需要从父亲直接推到儿子就行了。
因为一个父亲的儿子中只有一条边会改变,所以把转移的信息记录下来排序,根据每个儿子分别计算答案。
把一个边删掉后,在这条边之前(从大到小排序)的值不变,之后的会-1
问为什么的去看F的转移方程。
这里就不细说了因为太水
code
#include <iostream>#include <cstdio>#define fo(a,b,c) for (a=b; a<=c; a++)#define fd(a,b,c) for (a=b; a>=c; a--)using namespace std;int n,i,j,k,l,m2;int a[200001][3];int ls[200001];int fa[200001];int f[200001];int g[200001];int b[200002][2];int m[200002];int ans[200001];int max(int x,int y) {return (x>y?x:y);}int min(int x,int y) {return (x<y?x:y);}void qsort(int l,int r){ int i,j,k,mid; i=l; j=r; mid=b[(l+r)/2][0]; while (i<=j) { while (b[i][0]>mid) i++; while (b[j][0]<mid) j--; if (i<=j) { k=b[i][0]; b[i][0]=b[j][0]; b[j][0]=k; k=b[i][1]; b[i][1]=b[j][1]; b[j][1]=k; i++; j--; } } if (l<j) qsort(l,j); if (i<r) qsort(i,r); return;}void dfs(int t){ int i,j; f[t]=0; j=0; for (i=ls[t]; i; i=a[i][2]) dfs(a[i][1]); for (i=ls[t]; i; i=a[i][2]) b[++j][0]=f[a[i][1]]; qsort(1,j); fo(i,1,j) f[t]=max(f[t],b[i][0]+i); return;}void dfs2(int t){ int i,j; m2=0; j=0; for (i=ls[t]; i; i=a[i][2]) b[++j][0]=f[a[i][1]],b[j][1]=a[i][1]; if (fa[t]) b[++j][0]=g[t],b[j][1]=0; qsort(1,j); fd(i,j,1) m[i]=max(m[i+1],b[i][0]+i); fo(i,1,j) { if (b[i][1]) g[b[i][1]]=max(m2,m[i+1]-1); m2=max(m2,b[i][0]+i); } fo(i,1,j) m[i]=0; for (i=ls[t]; i; i=a[i][2]) if (ls[a[i][1]]) dfs2(a[i][1]); return;}int main(){ freopen("news.in","r",stdin); freopen("news.out","w",stdout); scanf("%d",&n); fo(i,1,n-1) { scanf("%d",&fa[i+1]); a[i][0]=fa[i+1]; a[i][1]=i+1; a[i][2]=ls[a[i][0]]; ls[a[i][0]]=i; } dfs(1); g[1]=0; dfs2(1); j=23333333; fo(i,1,n) { k=0; if (fa[i]) b[++k][0]=g[i]; for (l=ls[i]; l; l=a[l][2]) b[++k][0]=f[a[l][1]]; qsort(1,k); fo(l,1,k) ans[i]=max(ans[i],b[l][0]+l); ans[i]++; j=min(j,ans[i]); } printf("%d\n",j); fo(i,1,n) if (ans[i]==j) printf("%d ",i); printf("\n"); fclose(stdin); fclose(stdout); return 0;}
阅读全文
2 0
- JZOJ3501. 【NOIP2013模拟联考15】消息传递
- jzoj3501 【NOIP2013模拟联考15】消息传递(news) 树形dp
- 【NOIP2013模拟联考15】人类基因组(genes)
- 【NOIP2013模拟联考13】线段
- 【NOIP2013模拟联考7】数列
- 【NOIP2013模拟联考5】军训
- 【NOIP2013模拟联考6】选课
- 【NOIP2013模拟联考7】OSU
- SSL2864 【NOIP2013模拟联考15】物语(spfa优化)
- 【NOIP2013模拟联考5】军训(training)
- 【NOIP2013模拟联考6】选课(select)
- 【NOIP2013模拟联考5】军训(training) 题解
- NOIP2013模拟联考5】军训(training)
- 【NOIP2013模拟联考2】摘取作物(pick)
- 【NOIP2013模拟联考3】山峰(summits)
- 【NOIP2013模拟联考10】独立集(bubble)
- JZOJsenior3484.【NOIP2013模拟联考10】密码(substring)
- 【NOIP2013模拟联考14】图形变换(transform)
- c语言指针详解
- MongoDB GUI( Robo 3T) Shell使用及操作
- openvirtualpn
- map容器的黑科技
- 图论的第一步
- JZOJ3501. 【NOIP2013模拟联考15】消息传递
- FreeBASIC学习笔记——2.2 变量的声明
- Java获取当前时间的一天前的时间,一周前,一月前,一年前的时间
- 人工智能是大脑,物联网是身体
- 生日相同 2.0 【open judge】【结构体】
- 微信小程序如何使用阿里妈妈iconfont图标库
- PCB设计1:Altium designer模块化布局复用
- 推荐系统在百度云的实践
- 对称矩阵的判定