标签:存在 read ram lca -- perm sizeof printf ane
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 234 Accepted Submission(s): 82
【题意】给你一棵树,然后给你树的节点编号的一种排列,然后要你将这个序列分成非空的k份,对于每一份求lca的深度,然后累加, 求和最小。
【分析】首先得想到区间lca的一个性质,对于区间[i,j],他们的lca肯定是lca[i,i+1],lca[i+1,i+2],...lca[j-1,j]中的某一个,也就是说,对于某一个区间,决定lca的只有某相邻的两个数。然后在这个序列中,对于某一个数,他有三种存在状态。第一,它存在于某个区间,但是这个区间的lca不是由它决定的。第二,它一个数本身作为一份。第三,它和它左边的数的lca作为某一份的lca。然后dp[i][j]表示前i个数分成j段的最小答案,对于上面三种情况分别对应三个方程
dp[i][j]=min(dp[i][j],dp[i-1][j]);
dp[i][j]=min(dp[i][j],dp[i-1][j-1]+dep[a[i]]);
dp[i][j]=min(dp[i][j],dp[i-2][j-1]+lca[i]);
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define met(a,b) memset(a,b,sizeof a) #define pb push_back #define mp make_pair #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 5e5+50; const int M = 16000009; const int mod = 1e9+7; const double pi= acos(-1.0); typedef pair<int,int>pii; int n,k,ans; int dep[N],fa[N][20]; int a[N],lca[N]; vector<int>edg[N]; void dfs(int u,int f){ fa[u][0]=f; for(int i=1;i<20;i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } for(int v : edg[u]){ if(v==f)continue; dep[v]=dep[u]+1; dfs(v,u); } } int LCA(int u,int v){ int U=u,V=v; if(dep[u]<dep[v])swap(u,v); for(int i=19;i>=0;i--){ if(dep[fa[u][i]]>=dep[v]){ u=fa[u][i]; } } if(u==v)return (u); for(int i=19;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i];v=fa[v][i]; } } return (fa[u][0]); } int main(){ while(~scanf("%d%d",&n,&k)){ int dp[n+50][k+50]; met(dp,inf); for(int i=1;i<=n;i++)scanf("%d",&a[i]),edg[i].clear(); for (int i=1,u,v;i<n;i++){ scanf("%d%d",&u,&v); edg[u].pb(v); edg[v].pb(u); } dep[1]=1; dfs(1,0); dp[0][0]=0; for(int i=2;i<=n;i++){ int m = LCA(a[i-1],a[i]); lca[i]=dep[m]; } for(int i=1;i<=n;i++){ for(int j=0;j<=min(i,k);j++){ if(i-1>=j)dp[i][j]=min(dp[i][j],dp[i-1][j]); if(j>0)dp[i][j]=min(dp[i][j],dp[i-1][j-1]+dep[a[i]]); if(j>0&&i>=2&&j-1<=i-2)dp[i][j]=min(dp[i][j],dp[i-2][j-1]+lca[i]); } } printf("%d\n",dp[n][k]); } return 0; }
HDU 6065 RXD, tree and sequence (LCA DP)
标签:存在 read ram lca -- perm sizeof printf ane
原文地址:http://www.cnblogs.com/jianrenfang/p/7277317.html