[CF1394D] Boboniu and Jianghu

D - Boboniu and Jianghu

\(dp[i][0/1]\)表示当前链从下往上是不增/减的,那么当\(u\)\(v\)(其中\(fa[v]=u\))的\(b\)不相同时,\(dp[v][0/1]\)的第二维转移的状态是确定的,否则就是不确定的,这时直接强制其取\(0\),然后向每个点的\(vector\)中加入\(dp[v][1]-dp[v][0]\),从小到大排序,然后每次取前缀和的来改变转移的这些\(dp[v][0/1]\)的第二维的取值

转移时,对于取\(a[i]\)的个数,设\(cnt0\)\(cnt1\)分别表示转移状态中第二维取\(0\)\(1\)的个数,那么这也可以表示为第\(i\)个点的入度和出度,对于\(dp[i][0]\)\(a[i]\times\max(cnt0,cnt1+(i\neq1))\),对于\(dp[i][1]\)\(a[i]\times\max(cnt0+(i\neq1),cnt1)\),因为这些入的链可以在\(u\)处和出的链链接上

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N=2e5+5;
const ll INF=1e18;
int n,a[N],b[N];
int head[N],cnt=1;
struct node{
	int nxt,v;
}tree[N<<1];
void add(int u,int v){
	tree[++cnt]={head[u],v},head[u]=cnt;
	tree[++cnt]={head[v],u},head[v]=cnt;
}
ll dp[N][2];
void dfs(int u,int fa){
	ll sum=0;
	int cnt0=0,cnt1=0;
	vector<ll> val;
	for(int i=head[u],v;i;i=tree[i].nxt){
		if((v=tree[i].v)==fa) continue;
		dfs(v,u);
		if(b[u]>b[v]) sum+=dp[v][1],++cnt1;
		else if(b[u]<b[v]) sum+=dp[v][0],++cnt0;
		else sum+=dp[v][0],val.pb(dp[v][1]-dp[v][0]),++cnt0;
	}
	sort(val.begin(),val.end());
	for(int i=0;i<=val.size();++i){
		dp[u][0]=min(dp[u][0],sum+1ll*max(cnt0,cnt1+(u!=1))*a[u]);
		dp[u][1]=min(dp[u][1],sum+1ll*max(cnt0+(u!=1),cnt1)*a[u]);
		--cnt0,++cnt1;
		if(i==val.size()) continue;
		sum+=val[i]; 
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]),dp[i][0]=dp[i][1]=INF;
	for(int i=1;i<=n;++i) scanf("%d",&b[i]);
	for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),add(u,v);
	dfs(1,0);
	printf("%lld",min(dp[1][0],dp[1][1]));
	return 0;
}
posted @ 2023-10-10 16:41  LuoyuSitfitw  阅读(19)  评论(0)    收藏  举报