[JOISC 2021 Day4] 最悪の記者 4

Description

有 n n n 个人,第 i i i 个人的分数为 h i h_i hi​,修改 h i h_i hi​ 需要 c i c_i ci​ 元,要求 h i ≥ h a i h_i \ge h_{a_i} hi​≥hai​​,求最小修改费用。

Solution

首先考虑根据题目给出的不等关系建图,我们发现 Subtask 1 和 Subtask 2 就是一棵内向树,进一步推导出无特殊限制时的图为基环内向树森林。

考虑针对 Subtask 1 设计一个 O ( n 2 ) {\rm O}(n^2) O(n2) 的算法,容易发现应选择树形 DP。由于我们只需要判断修改后的 h i h_i hi​ 与原 h i h_i hi​ 的不等关系,所以可以将 h i h_i hi​ 离散化,方便存储空间。

我们设 f i , j f_{i,j} fi,j​ 为修改 h i h_i hi​ 为 j j j 后,满足 i i i 子树中的不等关系所需的最小花费,设 m m m 为离散化后的 h i h_i hi​ 上界。可以推导出状态转移方程

f i , j = c i × [ j ≠ h i ] + ∑ k ∈ s o n i min ⁡ j ≤ l ≤ m { f k , l } f_{i,j}=c_i \times [j\not=h_i]+\sum_{k \in {\rm son}_i} \min_{j \le l \le m} \big\{f_{k,l}\big\} fi,j​=ci​×[j​=hi​]+k∈soni​∑​j≤l≤mmin​{fk,l​}

这个算法虽然超时,但是是正确的,这启发我们进一步优化 DP 转移。优化到 O ( n ) {\rm O}(n) O(n) 比较不现实,考虑优化到 O ( n log ⁡ n ) {\rm O}(n \log n) O(nlogn)。

我们发现 f i , j f_{i,j} fi,j​ 中第二维有值的 c i × [ j ≠ h i ] c_i \times [j\not=h_i] ci​×[j​=hi​] 占数组的大部分,如果用数据结构来维护的话会增加许多赘余的操作。但是 c 1 ∼ c n c_{1} \sim c_n c1​∼cn​ 的和是不变的,因此我们可以将状态转移方程变成这样:

f i , j = ∑ k ∈ s o n i min ⁡ j ≤ l ≤ m { f k , l } − c i × [ j = h i ] f_{i,j}=\sum_{k \in {\rm son}_i} \min_{j \le l \le m} \big\{f_{k,l}\big\}-c_i \times [j=h_i] fi,j​=k∈soni​∑​j≤l≤mmin​{fk,l​}−ci​×[j=hi​]

然后再用 c 1 ∼ c n c_{1} \sim c_n c1​∼cn​ 的和加上 min ⁡ f 1 , i \min f_{1,i} minf1,i​,这样只需要进行单点减值,却有相同的效果,大大缩短了时间。

状态转移中只有简单的单点加值和区间查询最小值操作,不妨使用线段树维护 f i , j f_{i,j} fi,j​ 中的第二维,给每个点开一棵线段树显然不可行,因此想到采用线段树合并。

找区间最小值时的区间是 [ j , m ] [j,m] [j,m],然后再将每个子树中的最小值加起来。合并树 u u u 和树 v v v 时,我们可以记录 u min ⁡ u_{\min} umin​ 和 v min ⁡ v_{\min} vmin​ 为两棵树各自的最小值。设当前结点为 p p p 和 q q q,然后讨论 p + v min ⁡ p+v_{\min} p+vmin​ 是否小于 q + u min ⁡ q+u_{\min} q+umin​。

j j j 虽然不确定,但是右端点 m m m 是固定的。因此我们在合并时不可以用平常的方式合并,而是先合并右子树,再合并左子树。(想一想,为什么)然后简单维护 c i × [ j = h i ] c_i \times [j=h_i] ci​×[j=hi​] 的单点修改和合并时遇到一边空树的区间加标记就好了。

现在我们已经得到了针对 Subtask 1 和 Subtask 2 的 O ( n log ⁡ n ) {\rm O}(n \log n) O(nlogn) 树形 DP 算法。我们发现它同样适用于内向树森林,只需要对每一棵树分别跑一遍 DP 就好了。

对于基环树,我们可以先做一次拓扑排序或者 Tarjan 算法找强连通分量。找出环后将其看作一个点,将与环相连的所有子树的线段树进行合并。容易发现环上每个点的最终值一定相等,而且是环上的某个值或者最小值 1 1 1。于是我们枚举环的最终值,同时在线段树上查询 [ h i , m ] [h_i,m] [hi​,m] 的最小值更新答案。至此本题得到完整解法。

Warning

线段树合并的空间复杂度为 O ( n log ⁡ n ) {\rm O}(n \log n) O(nlogn) 而非 O ( n ) {\rm O}(n) O(n),还带点附加常数,因此请开 log ⁡ 2 ( 2 × 1 0 5 ) × 3 ≈ 54 \log_2 (2 \times 10^5) \times 3 \approx 54 log2​(2×105)×3≈54 倍空间。

Code

typedef long long LL;
const int N=2e5+5;int n,NumE,rb,tot,a[N],Fir[N],d[N],in[N],dfn[N];
LL Ret,h[N],c[N];inline LL Read() {LL x=0;char ch=getchar();while (ch<'0' || ch>'9') ch=getchar();while (ch>='0' && ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x;
}struct Edge {int v,nxt;}E[N];void AddE(int u,int v) {E[++NumE]={v,Fir[u]};Fir[u]=NumE;
}namespace Seg {int cnt,rt[N],nt[N],ls[N*54],rs[N*54];LL d1,d2,v[N*54],t[N*54];void Chg(int x,LL u) {if (x) v[x]+=u,t[x]+=u;}void Up(int x) {v[x]=min(v[ls[x]],v[rs[x]]);}void Dw(int x) {if (!t[x]) return;Chg(ls[x],t[x]),Chg(rs[x],t[x]),t[x]=0;}int Upd(int x,int l,int r,int p,LL k) {if (!x) x=++cnt;if (l==r) {v[x]=k;return x;}Dw(x);int mid=(l+r)>>1;if (p<=mid) ls[x]=Upd(ls[x],l,mid,p,k);else rs[x]=Upd(rs[x],mid+1,r,p,k);Up(x);return x;}LL Qry(int x,int l,int r,int L,int R) {if (!x) return 0;if (L<=l && r<=R) return v[x];Dw(x);int mid=(l+r)>>1;LL Res=0;if (L<=mid) Res=min(Res,Qry(ls[x],l,mid,L,R));if (R>mid) Res=min(Res,Qry(rs[x],mid+1,r,L,R));return Res;}int Mrg_Dfs(int p,int q,int l,int r) {if (!p && !q) return 0;if (!p) {d2=min(d2,v[q]),Chg(q,d1);return q;}if (!q) {d1=min(d1,v[p]),Chg(p,d2);return p;}if (l==r) {d1=min(d1,v[p]),d2=min(d2,v[q]);if (v[p]+d2<=v[q]+d1) {v[p]+=d2;return p;}else {v[q]+=d1;return q;}}Dw(p),Dw(q);int mid=(l+r)>>1;rs[p]=Mrg_Dfs(rs[p],rs[q],mid+1,r);ls[p]=Mrg_Dfs(ls[p],ls[q],l,mid);Up(p);return p;}int Mrg(int x,int y) {d1=d2=0;return Mrg_Dfs(x,y,1,rb);}
}using namespace Seg;struct Cir {LL h,c;bool operator<(const Cir& rhs) const {return h<rhs.h;}
};
vector<Cir> cr[N];void Dfs(int x) {for (int i=Fir[x];i;i=E[i].nxt) {Dfs(E[i].v);rt[x]=Mrg(rt[x],rt[E[i].v]);}rt[x]=Upd(rt[x],1,rb,h[x],Qry(rt[x],1,rb,h[x],rb)-c[x]);
}void PushT(int x) {dfn[x]=tot;cr[tot].push_back({h[x],c[x]});if (!dfn[a[x]]) PushT(a[x]);
}void TopS(int n) {queue<int> q;q=queue<int>();For(i,1,n) if (!in[i]) q.push(i);while (!q.empty()) {int u=q.front();q.pop();if (!--in[a[u]]) q.push(a[u]);}For(i,1,n) if (!dfn[i] && in[i])tot++,PushT(i);
}void Calc(int n) {For(i,1,n) if (!in[i] && in[a[i]])Dfs(i),nt[dfn[a[i]]]=Mrg(nt[dfn[a[i]]],rt[i]);For(i,1,tot) {sort(cr[i].begin(),cr[i].end());LL Cnt=v[nt[i]],sh=cr[i][0].h,sc=cr[i][0].c;For(j,1,cr[i].size()-1)if (sh==cr[i][j].h) sc+=cr[i][j].c;else {Cnt=min(Cnt,Qry(nt[i],1,rb,sh,rb)-sc);sh=cr[i][j].h,sc=cr[i][j].c;}Cnt=min(Cnt,Qry(nt[i],1,rb,sh,rb)-sc);Ret+=Cnt;}
}int main() {n=Read();For(i,1,n) {a[i]=Read(),h[i]=Read(),c[i]=Read();AddE(a[i],i),in[a[i]]++,d[i]=h[i],Ret+=c[i];}sort(d+1,d+n+1);rb=unique(d+1,d+n+1)-d-1;For(i,1,n) h[i]=lower_bound(d+1,d+rb+1,h[i])-d;TopS(n),Calc(n);printf("%lld",Ret);return 0;
}

「DP/DS Rec.」[JOISC 2021 Day4] 最悪の記者 4相关推荐

  1. 「DaoCloud 道客」入选 2021 中国高科技高成长瞪羚企业TOP50及云原生领域高成长企业

    " 十年 TO C,十年 TO B,中国高科技企业迎来 "数字中国的黄金十年". 为了更好地了解中国高科技高成长企业的现状和发展趋势,1 月 17 日,知名科技产业创投信 ...

  2. 「转型新范式」第四范式2021发布会全程直播倒计时

    6月23日,以"转型新范式"为主题的2021第四范式发布会暨企业智能化转型峰会如期而至.第四范式将携手金融.零售.制造.能源各行业的转型代表,分享智能化转型的成功实践,并通过发布更 ...

  3. 22岁天才少女加入华为俄罗斯研究院,曾获「编程界奥赛」冠军

    来源:新智元  怎样才能称得上「天才少年」? 中小学期间横扫竞赛,还拿下了编程界奥赛ICPC的冠军. 值得一提的是,年仅22岁的她刚刚加入了华为. 这位女孩便是Valeria Ryabchikova. ...

  4. 「JOISC 2020 Day4」治疗计划(线段树+dijkstra最短路)

    「JOISC 2020 Day4」治疗计划 description solution 设dpi:1−Ridp_i:1-R_idpi​:1−Ri​ 都能被救治成功的最小花费 两个治疗方案[Li,Ri], ...

  5. 四川省通江中学2021年高考成绩查询,「通江中学」2021年年通江中学升学率高不高?...

    为了让大家详细的了解关于通江中学的一些信息内容,四川中考升学网为大家整理了<「通江中学」2021年年通江中学升学率高不高?>这样一篇文章,一起来阅读一下,希望从这篇文章可以找到你想要的答案 ...

  6. Fortinet :《2021 年OT与网络安全现状报告》之「OT安全洞察」

    Fortinet年度报告<2021年OT与网络安全现状报告>旨在了解运营技术面临的威胁类型以及OT团队如何减轻这些威胁.为此,Fortinet 通过对员工人数超过2,500人的关键行业组织 ...

  7. 成都中考生专门学计算机哪个学校好,「计算机网络技术专业」2021年成都哪所计算机网络技术专业学校好_学校推荐...

    为了让大家详细的了解关于计算机网络技术专业的一些信息内容,四川中考升学网为大家整理了<「计算机网络技术专业」2021年成都哪所计算机网络技术专业学校好_学校推荐>这样一篇文章,一起来阅读一 ...

  8. 回顾2021虚拟与增强现实产业年会暨「金V奖」颁奖盛典

    摘要:6月18日,上海市北高新商务中心! 「金V起航,筑梦未来」,备受期待的2021虚拟与增强现实产业年会暨「金V奖」颁奖盛典将于6月18日13:30在上海市北高新商务中心隆重启幕! 2021虚拟与增 ...

  9. 「AI 质检员」在富士通上岗,效率比人工高 25%

    日本第一 IT 厂商富士通,于近日宣布开发了用于检测产品外观异常的 AI 技术,从而节省人力成本.材料成本等,同时也可节省声誉损失和退货/召回相关的成本,「无人工厂」已来. 来源 | Hyper超神经 ...

最新文章

  1. 微信小程序开发工具的基本应用
  2. Linux那些事儿 之 戏说USB(10)模型,又见模型
  3. Linux下oracle 9i图文安装二
  4. python课程设计报告总结-上海python课程设计报告目的
  5. CTF-Web-基础知识点汇总
  6. Spring中的@Cacheable开销
  7. pb 执行存储过程带参数_SQL高级知识——存储过程
  8. oracle同事查两个表,Oracle查询访问同一表的两个以上索引(三)
  9. C# 基础知识-09----.NET中SpecialFolder 类
  10. 日志系统实战(一)—AOP静态注入
  11. Python 中文数字对照表 输入一个数字,转换成中文数字。比如:1234567890 -> 壹贰叁肆伍陆柒捌玖零。【简单易懂,代码可以直接运行】
  12. 关于页眉的奇偶页不同设置和奇数页页眉展示每一章名称的设置方法
  13. 15 个为编程初学者准备的网站
  14. CentOS7快速配置服务器网卡聚合双bond方法
  15. 【面经】数据分析岗_面试题整理总结(持续更新中…)
  16. 从零开始Android游戏编程(第二版) 第一版前言
  17. 20221128-20221202周总结
  18. 微型计算机的 I3 I5是,i3与i5有什么区别
  19. 简历模板python爬虫
  20. 用express-hbs写layout

热门文章

  1. 大数据开源框架之HBase编程实践
  2. 安卓 Service的OnBind方法
  3. Git在项目中40个常用命令详解
  4. MySQL的默认隔离级别
  5. 被告人获取苹果iCloud账号 售卖公民信息牟利
  6. jquery 获取cookie值
  7. 【Python】工厂模式和建造者模式的区别
  8. Xilinx HLS实现AXI DMA
  9. 计算机主机电源有哪些,电脑常见的电源故障有哪些
  10. spring配置文件