UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈)

Description

一棵 n 个点的有根树,带点权 wi。
从 s 出发,希望达到 t,每秒可以从当前点移动到某一个儿子。
有一个死亡次数,初始为 0。若在某个点 i(i != s, t) 时,死亡次数 ≤ wi,那么死亡次数自增 1,并且立刻跳回到 s。
给出 q 组 s, t,求最短时间。
n, q ≤ 3×1053 \times 10^53×105

Solution

  • 每次从点 s 出生到撞程序猿死亡跟前几次是怎么死的并没有关系。所以对于每次 “从点 s 出生到撞程序猿死亡” 的过程都可以贪心选最近的点早死早超生。
  • 产生一个朴素的想法:记 gi,jg_i,_jgi,j 为当前在 i,已死亡 j − 1 次,再死一次所需时间。若 s, t 路径上最大点权为 W,那么答案为 ∑i=1Wgs,i+dis(s,t)\sum _{i=1}^W g_s,_i + dis(s, t)i=1Wgs,i+dis(s,t)
  • 这样设计状态的复杂度太大,发现 g 单调并且有大量状态相同。图像的话大概长这样:
    在这里插入图片描述
  • 优化:换个角度,考虑有多少次从出生到死亡的过程需要一秒,多少次需要两秒等等。
  • 具体来说,考虑记录 f[i][j] 表示 i 的子树中和 i 距离小于等于 j 的点的权值最大值。 这样 f[i][j]−f[i][j−1] 就等于有多少次从出生到死亡需要 j 秒。
  • 那么对于一个询问(s,t),答案就是
    ∑i=1d=dep[pos[mxval]]−dep[s](f[s][i]−f[s][i−1])∗i+dis(s,t)\sum_{i=1}^{d=dep[pos[mxval]]-dep[s]}(f[s][i]-f[s][i-1])*i+dis(s,t)i=1d=dep[pos[mxval]]dep[s](f[s][i]f[s][i1])i+dis(s,t)
    =f[s][d]∗d−∑i=1d−1f[s][i]+dis(s,t)=f[s][d]*d-\sum_{i=1}^{d-1}f[s][i]+dis(s,t)=f[s][d]di=1d1f[s][i]+dis(s,t)
  • 所以,可以把询问按照 s 挂在树上,想办法维护f,离线求解。
  • 考虑如何维护f。因为它与深度有关,所以考虑长链剖分。
  • 长链剖分完后有两种合并链的方法:
  1. 法一:用一个点v去更新f,是区间对一个数取max的操作,但因为f单调递增,所以可以二分出第一个大于 v 的位置,然后区间覆盖就可以了。这个可以用线段树实现。(推荐按照树剖的DFS序建一棵线段树,然后所有操作都可以在这一棵线段树上做。)
    时间复杂度 O((n+q)logn)O((n+q)logn)O((n+q)logn)
  2. 法二:若dep[j]<dep[k]且w[j]>w[k],那么k点显然可以不用维护了,发现删掉类似k的点后我们就得到了一个单调栈!因此我们决定维护一个子树内部按照深度排好序后对于 w 的单调栈。询问直接二分就好。注意点:1.我们需要求单调栈从栈顶到栈底的前缀和,但是不好维护,所以选择维护后缀和。2.栈的合并实际上按照任意顺序时间复杂度都是O(n)O(n)O(n),但是我们需要注意空间,为省空间,我们长链剖分之后按照DFS序分配空间即可。
    时间复杂度 O(n+qlogn)O(n+qlogn)O(n+qlogn)

Code

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=3e5+5;
struct Edge{int v,nxt;}edge[N];
int n,m,w[N],cnt,head[N];
int fa[N][25],mxw[N][25],len[N],son[N],dep[N],dfn[N],ind;
struct Query{int y,id;};
vector<Query> d[N]; 
long long ans[N];
int L[N],R[N],tot;
long long sum[N];//sum维护后缀和 
struct Stack{int dep,w;}stk[N],q[N];
//用stk来记录单调栈,是为了省空间
//按dfs序分配空间即可保证每个点对应的栈使用的stk区间无重叠部分 
void addedge(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void dfs1(int u){dep[u]=dep[fa[u][0]]+1;mxw[u][0]=w[fa[u][0]];for(int i=1;i<=20;i++){fa[u][i]=fa[fa[u][i-1]][i-1];mxw[u][i]=max(mxw[u][i-1],mxw[fa[u][i-1]][i-1]);}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;dfs1(v);if(len[v]>len[son[u]]) son[u]=v;}len[u]=len[son[u]]+1;
}
int get_mxw(int x,int y){int ret=0;for(int i=20;i>=0;i--)if(dep[fa[x][i]]>dep[y])ret=max(ret,mxw[x][i]),x=fa[x][i];return ret;
}
void add(int x,Stack a){//从x点的栈的左端加入新元素 //新加入元素的dep保证<=栈中元素的dep的最小值 while(L[x]<=R[x]&&stk[L[x]].w<=a.w) L[x]++;if(L[x]>R[x]){sum[--L[x]]=0;stk[L[x]]=a;} else{if(stk[L[x]].dep>a.dep){stk[--L[x]]=a;sum[L[x]]=sum[L[x]+1]+1ll*stk[L[x]+1].dep*(stk[L[x]+1].w-a.w);}}
}
void merge(int x,int y){//往x点的栈加入y点的栈中的元素时仍要满足x点的栈中的元素dep值从小到大排布 tot=0;while(L[x]<=R[x]&&stk[L[x]].dep<=stk[R[y]].dep) q[++tot]=stk[L[x]++];while(tot&&L[y]<=R[y])if(q[tot].dep>=stk[R[y]].dep) add(x,q[tot--]);else add(x,stk[R[y]--]);while(tot) add(x,q[tot--]);while(L[y]<=R[y]) add(x,stk[R[y]--]);
}
long long query(int u,int v){int mx=get_mxw(v,u),l=L[u],r=R[u],mid;while(l<=r){mid=l+r>>1;if(stk[mid].w<mx) l=mid+1;else r=mid-1;}if(stk[L[u]].w<=mx)return 1ll*sum[L[u]]- 1ll*sum[l] + 1ll*stk[L[u]].dep*stk[L[u]].w - 1ll*dep[u]*mx - 1ll*(stk[l].w-mx)*stk[l].dep;elsereturn 1ll*mx*(stk[l].dep-dep[u]);
}
void dfs2(int u){dfn[u]=++ind;if(son[u]){dfs2(son[u]);L[u]=L[son[u]];R[u]=R[son[u]];}else{L[u]=ind;R[u]=ind-1;}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==son[u]) continue;dfs2(v);merge(u,v);}for(int i=0;i<d[u].size();i++){int v=d[u][i].y;int id=d[u][i].id;ans[id]=query(u,v)+dep[v]-dep[u];}add(u,(Stack){dep[u],w[u]});
}
int main(){scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&w[i]);for(int i=2;i<=n;i++){scanf("%d",&fa[i][0]);addedge(fa[i][0],i);}dfs1(1);scanf("%d",&m);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);d[u].push_back((Query){v,i}); }dfs2(1);for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);return 0;
}

参考文章:
https://vfleaking.blog.uoj.ac/blog/2292
https://www.cnblogs.com/penth/p/9801945.html
https://blog.csdn.net/qq_42555009/article/details/100934540
https://blog.csdn.net/zxyoi_dreamer/article/details/101705010
https://blog.csdn.net/Mr_wuyongcong/article/details/111996460

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#系列之聊聊.Net Core的InMemoryCache

这两天在看.net core的in memory cache&#xff0c;这里记录一下用法&#xff0c;主要涉及MemoryCache的Get&#xff0f;Set&#xff0f;Expire&#xff0f;Flush。首先我们先用dotnet命令创建一个mvc的项目&#xff0c;这里我们将使用postman来请求server&#xff0c;1dotnet …

P1412-经营与开发【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P1412 题目大意 nnn个地点&#xff0c;有一个能力值为www的稿子 如果地点iii是资源型的&#xff0c;那么可以选择获得ai∗wa_i*wai​∗w的价值&#xff0c;且ww∗(1−k100)ww*(1-\frac{k}{100})ww∗(1−100k​)如果地点iii是…

纪中在家培训总结(2020.2.1~2020.2.24)

前言 因为新型冠状病毒&#xff08;疫情情况&#xff09;的原因&#xff0c;纪中培训改为在家培训&#xff0c;一天的进度变成了两天甚至三天的进度QAQ&#xff0c;但我还是想说&#xff1a;武汉加油&#xff01;中国加油&#xff01; 这次培训总结没啥好写&#xff0c;请勿嘲…

CF1137F Matches Are Not a Child‘s Play(树上数据结构问题、树链剖分+ODT)

Description 一棵 n 个点的树&#xff0c;点权最初为 1 ∼ n 的排列。 定义一个删点过程&#xff1a;每次找到权值最小的叶子&#xff0c;删去它以及连接的边&#xff0c;重复这个过程直到剩下一个点&#xff0c;然后删去最后的点。 处理 q 个询问&#xff1a; 将一个点 x 的…

小石的签到题

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 输入描述: 共一行&#xff0c;输入一个数 n 。 输出描述: 共一行&#xff0c;输出 “Shi” 或 “Yang”&…

值类型、引用类型和泛型的前世今生

值类型、引用类型和泛型多语言咱们先不说主题&#xff0c;先说说CLR支持多语言。 .net有个非常强大的特点&#xff0c;那就是跨语言&#xff0c;支持很多语言&#xff0c;比如C#、J#等。先来个图看一看C# J# VB 等等等

P3247-[HNOI2016]最小公倍数【分块,并查集】

正题 题目链接:https://www.luogu.com.cn/problem/P3247 题目大意 nnn个点mmm条边&#xff0c;每条边有(x,y,a,b)(x,y,a,b)(x,y,a,b)。qqq次询问(x′,y′,a′,b′)(x,y,a,b)(x′,y′,a′,b′)表示询问是否存在一条x′−>y′x->yx′−>y′的路径使得路径上amaxa′,bma…

【DP】奖励卡(jzoj 3937)

奖励卡 jzoj 3937 题目大意 现在有一场比赛&#xff0c;想观看的人要提交申请&#xff0c;现在有x个人提交后得到两个号&#xff0c;y个人提交后得到一个号&#xff0c;有n轮抽号&#xff0c;每一轮抽一个号&#xff08;概率相等&#xff09;&#xff0c;这个号的所有者不参…

CF526G Spiders Evil Plan(树上最优性问题、倍增+线段树)

Description 一棵 n 个结点的树&#xff0c;有正边权。 用 y 条链覆盖这棵树&#xff0c;满足&#xff1a; 所有链连通&#xff08;有重点即算作相连&#xff09;点 x 被覆盖被覆盖的边的权值和尽可能大 q 次给出 x, y&#xff0c;询问最大边权和&#xff0c;强制在线。 n, q…

CAP带你轻松玩转ASP.NETCore消息队列

CAP是什么&#xff1f;CAP是由我们园子里的杨晓东大神开发出来的一套分布式事务的决绝方案&#xff0c;是.Net Core Community中的第一个千星项目&#xff08;目前已经1656 Start&#xff09;&#xff0c;具有轻量级、易使用、高性能等特点。https://github.com/dotnetcore/CAP…

装备合成

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 输入描述: 输入包含t组数据 第一行一个整数t 接下来t行每行两个整数x,y 输出描述: 每组数据输出一行一个…

P4161-[SCOI2009]游戏【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P4161 题目大意 一个1∼n1\sim n1∼n的排列&#xff0c;f(x)f(x)f(x)表示在置换xxx下置换多少次才能回到原来的排列&#xff0c;求在所有置换下f(x)f(x)f(x)的所有可能的值的数量。 解题思路 一个置换的fff值就是这个置换的…

【spfa】假期计划(jzoj 3936)

假期计划 jzoj 3936 题目大意 给你一个有向图&#xff08;n,m⩽20000n,m\leqslant 20000n,m⩽20000&#xff09;&#xff0c;现在有一些作为枢纽的点&#xff0c;且保证每一条边的两个点至少有一个是枢纽点&#xff0c;现在给q个询问&#xff0c;问某一个点到另一个点的最短…

CF650E Clockwork Bomb(树上构造类问题、并查集)

Description 给出两棵 n 结点的有标号树。 每次操作删去第一棵树的一条边&#xff0c;再加上一条边&#xff0c;需要保证此时还是一棵树。 构造一种操作序列&#xff0c;将第一棵树变成第二棵树&#xff0c;使得操作数最小。 n ≤ 51055 \times 10^55105 Solution 显然&…

微软必应从.NET Core 2.1获得了性能提升

据微软工程师Mukul Sabharwal介绍&#xff0c;在将微软搜索引擎必应迁移到.NET Core 2.1之后&#xff0c;内部服务延迟降低了34%&#xff0c;这主要归功于.NET社区贡献的改进。按照Sabharwal的说法&#xff0c;.NET Core的多项改进贡献了大部分的性能提升&#xff0c;包括字符串…

阶乘

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 给定一个正整数 p 求一个最小的正整数 n&#xff0c;使得 n! 是 p 的倍数 输入描述: 第一行输入一个正整数…

P2151-[SDOI2009]HH去散步【矩阵乘法】

正题 题目链接:https://www.luogu.com.cn/problem/P2151 题目大意 nnn个点mmm条边的一张无向图&#xff0c;走过一条边后下一次就不能再走这条&#xff0c;求AAA到BBB之间有多少长度为ttt的路径。 解题思路 因为有不能再走同一条的限制&#xff0c;所以不能直接裸上矩乘&…

IQ测试(jzoj 5048)

IQ测试 jzoj 5048 题目大意 给出一个序列a&#xff0c;然后有m个询问&#xff0c;每个询问给出一个序列&#xff0c;问这个序列是否可以由序列a删掉一些数得到的 输入样例 7 1 5 4 5 7 8 6 4 5 1 5 5 8 6 3 2 2 2 3 5 7 8 4 1 5 7 4输出样例 TAK NIE TAK NIE数据范围 对…

CF1088F Ehab and a weird weight formula(树上最优性问题、贪心+倍增)

Description 给出一棵 n 个结点的树&#xff0c;点 i 有正权值 wiw_iwi​&#xff0c;wiw_iwi​ 互不相同。 除了权值最小的点&#xff0c;保证每个点 u 都有一个邻点 v 使得 wvw_vwv​ < wuw_uwu​。 构造一棵树&#xff0c;最小化代价&#xff1a; 对于每个点 u&#xf…

搭建基于云端的中间层以支持跨平台的智能视觉服务

不断演进的应用场景初级应用场景—宅在家里场景&#xff1a;Bob同学有一天在网上看到了一张建筑物的图片&#xff0c;大发感慨&#xff1a;"好漂亮啊&#xff01;这是哪里&#xff1f;我要去亲眼看看&#xff01;"Bob同学不想问别人&#xff0c;可笑的自尊心让他觉得…