http://uoj.ac/problem/418

题解

考虑激活每个节点时,它的每个儿子都是放满的。

那每一次的操作我们可以用一个二元组来表示\((w_i-\sum w_{son},\sum w_{son})\)。

表示这一次操作完后的增量和这次操作中石子数达到的峰值。

那么一个节点被操作当且仅当它的所有儿子都被操作。

这样很不好处理,所以我们把整个操作序列倒过来,这样限制一个点的只有他的父亲。

那么二元组会变成:\((\sum w_{son}-w_i,\sum w_{son})\),我们还是需要最小化这个序列的历史最值,因为按照这个序列模拟的话是可以还原出它的每一个时刻的。

然后考虑贪心,我们需要对每一个操作求出它的优先度。

对于\(x<0\)的操作,它显然放在前面会更优,如果有多个\(<0\)的操作,\(y\)更小的放在前面。

对于\(x\geq 0\)的操作,我们要让(x,y)优于(dx,dy),那么就有:

\[max(y,dy+x)<max(dy,dx+y)
\]

前面的常量先不管。

\[dy+x<dx+y ->x-y>dx-dy
\]

于是我们弄清楚了每个元素的优先度,然后我们求出全局的一个最优序列。

每次找到最优的,如果这个点还没有被父亲激活,那么就和父亲合并。

通过观察我们发现每棵子树的最优序列是全局的子序列,然后我们可以线段树合并求答案。

代码

  1. #include<bits/stdc++.h>
  2. #define N 200002
  3. #define ls tr[cnt].l
  4. #define rs tr[cnt].r
  5. using namespace std;
  6. typedef long long ll;
  7. int f[N],n,id[N],fa[N],T[N],tott,nxt[N];
  8. bool vis[N];
  9. ll w[N],s[N],ans[N],val[N];
  10. inline ll rd(){
  11. ll x=0;char c=getchar();bool f=0;
  12. while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  13. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  14. return f?-x:x;
  15. }
  16. vector<int>vec[N];
  17. int find(int x){return f[x]=f[x]==x?x:find(f[x]);}
  18. struct node{
  19. ll x,y;
  20. int h,t;
  21. inline node operator +(const node &b)const{return node{x+b.x,max(y,x+b.y),h,b.t};}
  22. inline bool operator <(const node &b)const{
  23. int o1=x>=0,o2=b.x>=0;
  24. if(o1!=o2)return x<b.x;
  25. if(!o1){
  26. if(y!=b.y)return y<b.y;
  27. return h<b.h;
  28. }
  29. if(y-x!=b.y-b.x)return y-x>b.y-b.x;
  30. return h<b.h;
  31. }
  32. };
  33. struct seg{
  34. node x;
  35. int l,r;
  36. }tr[N*23];
  37. node pre[N];
  38. set<node>q;
  39. int merge(int u,int v){
  40. if(!u||!v)return u|v;
  41. tr[u].l=merge(tr[u].l,tr[v].l);
  42. tr[u].r=merge(tr[u].r,tr[v].r);
  43. tr[u].x=tr[tr[u].l].x+tr[tr[u].r].x;
  44. return u;
  45. }
  46. void ins(int &cnt,int l,int r,int x,int id){
  47. cnt=++tott;
  48. if(l==r){
  49. tr[cnt].x=node{val[id],s[id],l,l};
  50. return;
  51. }
  52. int mid=(l+r)>>1;
  53. if(x<=mid)ins(ls,l,mid,x,id);
  54. else ins(rs,mid+1,r,x,id);
  55. tr[cnt].x=tr[ls].x+tr[rs].x;
  56. }
  57. void dfs(int u,int fa){
  58. ins(T[u],1,n,id[u],u);
  59. for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
  60. int v=*it;
  61. dfs(v,u);
  62. T[u]=merge(T[u],T[v]);
  63. }
  64. ans[u]=tr[T[u]].x.y+w[u];
  65. }
  66. int main(){
  67. int TT=rd();
  68. n=rd();
  69. for(int i=2;i<=n;++i)fa[i]=rd(),vec[fa[i]].push_back(i);
  70. for(int i=1;i<=n;++i)w[i]=rd(),s[fa[i]]+=w[i],f[i]=i;
  71. for(int i=1;i<=n;++i){
  72. val[i]=s[i]-w[i];
  73. pre[i]=node{val[i],s[i],i,i};
  74. q.insert(pre[i]);
  75. }
  76. vis[0]=1;
  77. int now=0;
  78. while(!q.empty()){
  79. set<node>::iterator it=q.begin();
  80. node x=*it;
  81. q.erase(it);
  82. if(vis[fa[x.h]]){
  83. nxt[now]=x.h;
  84. while(now!=x.t)vis[now]=1,now=nxt[now];
  85. vis[now]=1;
  86. }
  87. else{
  88. int pr=find(fa[x.h]);
  89. q.erase(pre[pr]);
  90. nxt[pre[pr].t]=pre[x.h].h;
  91. pre[pr]=pre[pr]+pre[x.h];
  92. f[find(x.h)]=pr;
  93. q.insert(pre[pr]);
  94. }
  95. }
  96. int cnt=0;
  97. now=0;
  98. for(int i=1;i<=n;++i){
  99. cnt++;
  100. now=nxt[now];
  101. id[now]=i;
  102. }
  103. dfs(1,0);
  104. for(int i=1;i<=n;++i)printf("%lld ",ans[i]);
  105. return 0;
  106. }

UOJ418. 【集训队作业2018】三角形的更多相关文章

  1. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  2. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  3. [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥

    题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...

  4. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  5. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  6. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

  7. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

  8. UOJ#422. 【集训队作业2018】小Z的礼物

    #422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...

  9. UOJ#428. 【集训队作业2018】普通的计数题

    #428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...

  10. uoj450 【集训队作业2018】复读机(生成函数,单位根反演)

    uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...

随机推荐

  1. C语言第十一周作业

        这个作业属于哪个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/computer-scienceclass3-2018/ ...

  2. [19/05/27-星期一] JavaScript_ 条件语句(if语句)和循环语句(while 、for、do-while)

    一.条件语句 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  3. MySQL-快速入门(12)备份、还原

    1.数据备份 1>使用MySQLdump命令备份(主要的方式) //备份数据库中某张表(去掉表的限定,就是备份指定数据库)//备份脚本可以重新创建表及插入数据mysqldump -u user ...

  4. oracle跟SQL Server 2005 的区别

    Oracle与Sql server的区别   一直搞不明白Oracle数据库和sql server的区别,今天我特意查资料把他们的区别整理出来 Oracle数据库:Oracle Database,又名 ...

  5. RabbitMq学习6-安装php-amqplib(RabbitMQ的phpAPI)

    一.使用composer安装php-amqplib 1.在你的项目中添加一个 composer.json文件: { "require": { "php-amqplib/p ...

  6. HNUSTOJ-1675 Morse Code(DFS+字典序搜索)

    1675: Morse Code 时间限制: 2 Sec  内存限制: 128 MB提交: 73  解决: 33[提交][状态][讨论版] 题目描述 摩尔斯电码(英语:Morse Code)是一种时通 ...

  7. 2019牛客暑期多校训练营(第八场) - B - Beauty Values - 水题

    https://ac.nowcoder.com/acm/contest/888/B 实际上的确是个水题,写个小数据找个规律看看,所谓不同度,其实就是依次插入每个元素后,各种元素出现的最后位置的坐标求和 ...

  8. JS中For循环中嵌套setTimeout()方法的执行顺序

    在For循环中执行setTimeOut()方法的代码,执行顺序是怎样的呢? 代码如下 function time() { for(var i= 0;i<5;i++){ setTimeout(fu ...

  9. Testbench学习笔记

    Testbench学习笔记(一) 书写testbench是数字电路设计中不可或缺的一项设计方法,主要是提供的是激励.尽管现在各种开发工具都通过绘制波形图的方法生成测试激励,测试书写的代码,但是其不可移 ...

  10. vscode 黑屏及类名报错解决方案

    1.安装vscode之后打开黑屏,解决方案如下图,右键--属性--兼容性--勾选上 2.vscode 类名总报错 是ES2017的语法修饰器引起vscode警告. 解除的方法如果你使用的typescr ...