[JZOJ3987]Tree
题目大意
给定一棵有nn个节点的点带权(viv_i)无根树。你需要选择一些互不相交(包括端点)的路径。如果你选择了kk条路径,且覆盖的点权和为SS,得分就为Sk+1\frac S{k+1}。
另外,在选取路径之前,你必须执行一次如下的操作(操作分为三个步骤):
- 选定整数参数CC,满足C∈[0,T]C\in[0,T]
- 将所有点权加上CC
- 将所有点权对LIMITLIMIT取模。
其中TT,LIMITLIMIT的值已经被给出,你需要求出可能的最大得分。
1≤n≤5×103,vi,t<LIMIT≤1051\le n\le5\times10^3,v_i,t\lt LIMIT\le10^5
题目分析
先不考虑必须要执行的操作,假设我知道每一个点的权值,怎么做呢?
分数规划的常见套路:考虑二分答案ansans,那么当前答案可行当且仅当存在方案满足:
\frac{S}{k+1}>ans
即
S-k\times ans>ans ]
那么怎么判断当前答案是否可行呢?可以发现,如果我们在计算时将每一条路径各自带来的得分都减去 ansans,那么左边式子是可以看成与路径条数 kk无关的。
因此我们使用动态规划算法来判定答案是否可行。我们随便选一个根节点,设fif_i和 gig_i分别表示节点 ii向上延伸/不向上延伸(包括它作为两个儿子向上延伸的交点和不选它两种情况),子树ii的最大得分。
这个瞎讨论一下就可以转移,时间复杂度是 O(n)\mathrm O(n)的。也就是说我们可以在线性时间内完成对答案可行性的判定。
那么现在要考虑执行操作,显然我们没有必要对于 [0,T][0,T]内的每一个数都考察一遍,因为如果有很多个 CC,它们都不会造成任何一个viv_i被 LIMITLIMIT模掉,那么显然这些 CC中最大那个会造成更优的结果。因此我们只用考察LIMIT−vi−1LIMIT-v_i-1这种数(当然还要判断是否小于等于 TT之类的)。令EE表示二分答案次数,现在时间复杂度是 O(n2E)\mathrm O(n^2E)。
这让还不能得到所有分数,怎么办呢?
在这题,我们可以线性判断对于一个点权序列,一个答案是否可行,但是要具体求出对于这个点权序列的最优解,就要算上二分的复杂度。
那么我们考虑加上一个优化,每次二分之前,先判定对于当前要考察的点权序列,目前的最优解是否可行,如果不可行,那么在这个点权序列我们不可能计算出更加优的结果,就不用在这里二分了。
但是这样我依然有可能每次都要二分,毕竟有可能很不好运,每一个考察值的答案都比前一个优。那怎么办?我们随机化!
将所有考察值去重,然后随机打乱,使用上面的方法判断。这样期望只会有 logn\log n个值要进行二分。这个证明需要用到一下结论:
- 一个nn个数随机顺序的排列,我们从第一个数开始,每次跳到后面第一个比自己大的位置,期望情况下需要logn\log n步。
- 证明:根据期望的线性性,我们只要计算出每一个位置对步数造成贡献的概率之和。显然一个位置ii对答案造成贡献当且仅当在它前面没有更大的数,这个概率为1i\frac 1 i,我们累加起来就是调和级数,是O(logn)\mathrm O(\log n)的。
于是这里的时间复杂度变为O(n2+nElogn)\mathrm O(n^2+nE\log n)了。
代码实现
请注意代码常数……
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>using namespace std;typedef double db;const db EPS=1e-8;
const db INF=1e+40;
const int N=5005;
const int E=N<<1;int c[N],v[N],last[N];
int nxt[E],tov[E];
int n,T,LIM,tot,m;
db f[N],g[N];
db ans,sum;void insert(int x,int y){tov[++tot]=y,nxt[tot]=last[x],last[x]=tot;}void dfs(int x,int fa,db cur)
{f[x]=-cur,g[x]=0.0;db d1=-INF,d2=-INF,gsum=0.0;for (int i=last[x],y;i;i=nxt[i])if ((y=tov[i])!=fa){dfs(y,x,cur);gsum+=g[y];if (d1<f[y]-g[y]) d2=d1,d1=f[y]-g[y];else if (d2<f[y]-g[y]) d2=f[y]-g[y];}f[x]=max(f[x],d1)+gsum+v[x];g[x]=max(g[x],max(d1+d2+cur+v[x],d1+v[x]))+gsum;
}bool judge(db cur)
{dfs(1,0,cur);return max(f[1],g[1])>=cur;
}db calc(db l,db r)
{db mid,ret=l;for (;r-l>=EPS;){mid=(l+r)/2.0;if (judge(mid)) l=(ret=mid)+EPS;else r=mid-EPS;}return ret;
}void solve()
{ans=0.0;for (int i=1;i<=m;i++){for (int j=1;j<=n;j++) v[j]+=c[i],v[j]>=LIM?v[j]-=LIM:0;if (judge(ans)) ans=calc(ans,sum);for (int j=1;j<=n;j++) v[j]-=c[i],v[j]<0?v[j]+=LIM:0;}
}int main()
{srand(time(0));freopen("tree.in","r",stdin),freopen("tree.out","w",stdout);scanf("%d%d",&n,&LIM);for (int i=1;i<=n;i++) scanf("%d",&v[i]),sum+=v[i]+LIM;for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y),insert(y,x);scanf("%d",&T);for (int i=1;i<=n;i++) c[i]=min(T,LIM-1-v[i]);sort(c+1,c+1+n);m=0;for (int i=1;i<=n;i++) if (i==1||c[i]!=c[m]) c[++m]=c[i];random_shuffle(c+1,c+1+m);solve();printf("%.6lf\n",ans);fclose(stdin),fclose(stdout);return 0;
}
[JZOJ3987]Tree相关推荐
- 107. Binary Tree Level Order Traversal II
题目 Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from l ...
- 102. Binary Tree Level Order Traversal
题目 Binary Tree Level Order Traversal 层次遍历二叉树 链接 Given a binary tree, return the level order traversa ...
- Python---哈夫曼树---Huffman Tree
今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...
- [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...
- Code Forces Bear and Forgotten Tree 3 639B
B. Bear and Forgotten Tree 3 time limit per test2 seconds memory limit per test256 megabytes inputst ...
- Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)
Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈) 标签: codeforces 2017-06-02 11:41 29人阅读 ...
- datagrid底部显示水平滚动_DevExpress WPF v19.1:Data Grid/Tree List等控件功能增强
行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部 ...
- java easyui tree例子_EasyUI Tree的简单使用
此前写过zTree插件的demo,没有记录下来,这次记录一下EasyUI的Tree. 实现效果:获取数据库表的数据,以树结构的形式展示出来. 树结构数据分为同步加载和异步加载,同步加载就是初始化加载时 ...
- windows用 tree命令查看目录文件夹结构
windows用 tree命令查看目录文件夹结构 ## 查看帮助 tree --helptree --dirsfirst --filelimit 6 -h -t –dirsfirst 目录优先展示 – ...
- PCL :K-d tree 2 结构理解
K-d tree 基础思路:(先看之前的KNN思想,更容易理解) 导语:kd 树是一种二叉树数据结构,可以用来进行高效的 kNN 计算.kd 树算法偏于复杂,本篇将先介绍以二叉树的形式来记录和索引空间 ...
最新文章
- Kotlin 在kotlin内使用Java的一些注意(长篇)
- TreeView查获节点并选中节点
- Object-c基础之一:#import,NSLog(),数据类型
- .net如何引用该命名空间
- oracle数据恢复
- Python_Python处理JSON文件
- atitit.印度教与java宗教的特点与观念对比 attilax总结
- APP抓包之fiddler使用介绍
- 2018-8-10-git-push-错误-hook-declined-
- python四分位数_四分位数计算过程
- C语言的进制转换以及算法实现
- 云词:让英语学习平步青云
- 【loj】#10064. 「一本通 3.1 例 1」黑暗城堡(最短路径生成树 dijkstra+Prim)
- python提醒事件_利用python实现短信和电话提醒功能的例子
- 深圳计算机专业中专学校,深圳中专学校
- TP50 TP90 TP95 TP99 TP999 TP9999
- Android 实现仿微信朋友圈全文、收起的功能
- Typora 是什么?
- XmlHttp的open( )方法
- linux svn 忽略指定文件
热门文章
- LM3886TF功放制作进展
- 人居一世间, 忽若风吹尘 2019.07.07.
- 伸缩式工具刀行业调研报告 - 市场现状分析与发展前景预测
- 编译Android版本的chromium浏览器
- burst什么意思_burst是什么意思_burst在线翻译_英语_读音_用法_例句_海词词典
- 百度重度依赖者谈谈恶意点击
- Excel中文转拼音(完整版)-转
- Jenkins自动集成
- android 音量曲线,Android音量控制曲线
- SAS数据导入input要点