ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[uoj84]水题走四方

2022-02-22 13:03:56  阅读:132  来源: 互联网

标签:水题 dep max 四方 mx fa uoj84 节点 瞬移


瞬移后无法区分两者,分开时不妨称下一次瞬移的为分身,即仅允许分身瞬移回本身

考虑本身,即从根节点出发向下移动的一条路径,并称路径上分身曾瞬移到的点为关键节点(包括根节点)

对关键节点dp,定义$f_{k}$表示当前两者均在$k$且$k$子树外所有点均被经过的最短时间

枚举上一个关键节点,分析两者的移动,不难得到转移即
$$
f_{k}=\min_{x为k的祖先}\big(f_{x}+(g_{x}-g_{k})-dep_{x}(h_{x}-h_{k})+\max(dep_{k}-\max(d_{\max},dep_{x}),0)\big)
$$
(其中$dep_{k}$表示$k$的深度$,h_{k}$表示$k$子树中叶子个数$,g_{k}$表示$k$子树中叶子深度和$,d_{\max}$表示$x$子树内除$k$子树外最深的叶子)

另外,初始状态即$f_{1}=1$,最终答案即$\min f_{k}+g_{k}-dep_{k}h_{k}$

若$d_{\max}\ne 0$且$dep_{k}>d_{\max}$,可以理解为其到达深度为$d_{\max}$的点后分身直接瞬移,显然这样不劣

同时,若$d_{\max}=0$,即$x$到$k$的这条链上(除$k$以外)没有其他儿子,直接从$x=fa_{k}$依次转移即可

进一步的,若$x$不是第一个满足$dep_{k}\le d_{\max}$的祖先,那么不妨先转移到该祖先再转移到$k$,代入可得不劣

综上,仅需考虑$x=fa_{k}$(在$fa_{k}$仅有$k$一个儿子时)和第一个满足$dep_{k}\le d_{\max}$的祖先

关于后者,对树长链剖分,注意到其所在长链顶端的父亲一定满足

换言之,每一条长链内是独立的,分别维护一个单调栈执行上述过程即可

需要注意空间限制,由于保证编号,可以使用遍历的方式代替dfs

时间复杂度为$o(n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 5000005
 4 #define ll long long
 5 vector<int>V[N];
 6 int n,n0,st[N],vis[N],fa[N],dep[N],h[N],mx[N],cmx[N],son[N],top[N];
 7 ll ans,g[N],f[N];
 8 char s[N<<1];
 9 void get_val(int k,int x,int mx){
10     f[k]=min(f[k],f[x]+(g[x]-g[k])-(ll)dep[x]*(h[x]-h[k])+max(dep[k]-max(mx,dep[x]),0));
11 }
12 int main(){
13     scanf("%d%s",&n,s+1);
14     for(int i=1;i<=(n<<1);i++)
15         if (s[i]==')')st[0]--;
16         else{
17             n0++;
18             if (st[0]){
19                 fa[n0]=st[st[0]];
20                 vis[st[st[0]]]=1;
21             }
22             st[++st[0]]=n0;
23         }
24     for(int i=2;i<=n;i++)dep[i]=dep[fa[i]]+1;
25     for(int i=n;i>1;i--){
26         if (!vis[i])h[i]=1,mx[i]=g[i]=dep[i];
27         h[fa[i]]+=h[i],g[fa[i]]+=g[i];
28         int d=mx[i];
29         if (mx[fa[i]]<d)son[fa[i]]=i,swap(mx[fa[i]],d);
30         cmx[fa[i]]=max(cmx[fa[i]],d);
31     }
32     for(int i=1;i<=n;i++){
33         if ((i==1)||(son[fa[i]]!=i))top[i]=i;
34         else top[i]=top[fa[i]];
35         V[top[i]].push_back(i);
36     }
37     memset(f,0x3f,sizeof(f));
38     f[1]=0;
39     for(int i=1;i<=n;i++)
40         if (!V[i].empty()){
41             if (i!=1){
42                 for(int j=0;j<V[i].size();j++)get_val(V[i][j],fa[i],mx[fa[i]]);
43             }
44             st[0]=0;
45             for(int j=0;j<V[i].size();j++){
46                 if (j)get_val(V[i][j],V[i][j-1],cmx[V[i][j-1]]);
47                 while ((st[0])&&(cmx[st[st[0]]]<dep[V[i][j]]))st[0]--;
48                 if (st[0])get_val(V[i][j],st[st[0]],cmx[st[st[0]]]);
49                 while ((st[0])&&(cmx[st[st[0]]]<=cmx[V[i][j]]))st[0]--;
50                 st[++st[0]]=V[i][j];
51             }
52         }
53     ans=1e18;
54     for(int i=1;i<=n;i++)ans=min(ans,f[i]+g[i]-(ll)dep[i]*h[i]);
55     printf("%lld\n",ans);
56     return 0;
57 } 
View Code

 

标签:水题,dep,max,四方,mx,fa,uoj84,节点,瞬移
来源: https://www.cnblogs.com/PYWBKTDA/p/15922597.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有