HDU多校2020 第八場 1012/6866--Linuber File System(樹上DP
阿新 • • 發佈:2020-08-13
題意:http://acm.hdu.edu.cn/showproblem.php?pid=6866
每個節點都有值域區間,一開始每個點值都為0,你每次可以選一個子樹都+x,-x,0(任意),問最終所有節點滿足值域的最小操作次數。
思路:
dp開二維,第二維計個值域區間,n方瞎搞搞就行,場上明顯榜被帶歪了,簽到題水平(狗頭)
程式碼有改動,可能不AC
int a[N],b[N],vl[N],vr[N]; int LS(int n) { int m=0; for(int i=1;i<=n;++i) b[++m]=a[i]; sort(b+1,b+1+m); m=unique(b+1,b+1+m)-b-1; for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+m,a[i])-b; return m; } int top; int dp[2010][8010]; void dfs(int u,int f) { for(int i=1;i<=top;++i)dp[u][i]=0; for(int i=head[u];i;i=edge[i].next) { int to=edge[i].to; if(to==f)continue; dfs(to,u); for(int j=1;j<=top;++j)dp[u][j]+=dp[to][j]; } int L=vl[u]*2,R=vr[u]*2; if(L>R)swap(L,R); int min_=INF; for(int i=L;i<=R;++i)min_=min(min_,dp[u][i]); for(int i=1;i<=top;++i) { if(i<L||i>R) { dp[u][i]=1+min_; } else { if(dp[u][i]!=min_) dp[u][i]=1+min_; } } } void solve() { int n; cin>>n; Init(n); for(int i=1;i<n;++i) { int u,v; cin>>u>>v; add(u,v); add(v,u); } for(int i=1;i<=n+n;++i)cin>>a[i]; a[n+n+1]=0; top=LS(n+n+1); for(int i=1,j=1;i<=n+n;i+=2,++j) vl[j]=a[i],vr[j]=a[i+1]; top=top*2+1; dfs(1,0); int ans=dp[1][a[n+n+1]*2]; cout<<ans<<endl; }