zoukankan      html  css  js  c++  java
  • 东非大裂谷

    ### Description

      数据范围:(1<=N<=10^5,1<=W_i<=10^9)

      

    Solution

      感觉最近有点不在状态。。这题场上居然没做出来也是服了

      (代爷:“这不是普及组题吗?”,然后7minA掉了qwq)

      从满足题意的分组的性质入手:

    (1)如果一条链是一组,那么这条链的两个端点的值一定分别对应最大值和最小值(否则把这个点从这条链里面去掉,然后并到另一组里面并不会使答案变劣)

    (2)如果一条链是一组,那么这条链的点权值随深度增加单调递增或递减(如果不单调的话,我们可以从破坏单调性的地方断开变成多条链,并不会使答案变劣)

    ​  有了这两个性质之后dp就很显然了

      我们对于每一个点维护该点为链头的链中递增或递减时子树内的答案最大值,(f[x][0])表示递增的答案,(f[x][1])表示递减的答案,记(sum=sumlimits_{uin son(x)}max(f[u][0],f[u][1])),那么有:

    [egin{aligned} &(uin son(x)&&w[u]>w[x])\ &f[x][0]=max(sum-max(f[u][0],f[u][1])+f[u][0]+w[u]-w[x])\ \ &(uin son(x)&&w[u]<w[x])\ &f[x][1]=max(sum-max(f[u][0],f[u][1])+f[u][1]+w[x]-w[u]) end{aligned} ]

      最后(ans=max(f[x][0],f[x][1],sumlimits_{uin son(1)}max(f[u][0],f[u][1])))

      

      mark:(弱智操作)dp的时候不要想当然地忽略掉路径上其他分叉的贡献。。

    ​  mark:单调性单调性单调性qwq

      

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int N=1e5+10;
    struct xxx{
    	int y,nxt;
    }a[N*2];
    int h[N],w[N];
    ll f[N][2];
    int n,m,tot;
    ll ans;
    void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
    void dfs(int x){
    	int u;
    	ll sum=0;
    	for (int i=h[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		dfs(u);
    		sum+=max(f[u][0],f[u][1]);
    	}
    	f[x][0]=f[x][1]=sum;
    	for (int i=h[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		if (w[x]<=w[u])
    			f[x][0]=max(f[x][0],sum-max(f[u][0],f[u][1])+f[u][0]+w[u]-w[x]);
    		if (w[x]>=w[u])
    			f[x][1]=max(f[x][1],sum-max(f[u][0],f[u][1])+f[u][1]+w[x]-w[u]);
    	}
    	if (x==1){
    		ans=sum;
    		ans=max(ans,max(f[x][0],f[x][1]));
    	}
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y;
    	scanf("%d",&n);
    	memset(h,-1,sizeof(h));
    	tot=0;
    	for (int i=1;i<=n;++i) scanf("%d",w+i);
    	for (int i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		add(x,y); 
    	}
    	ans=0;
    	dfs(1);
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    vc++操作mysql数据库的技巧
    [翻译]用表单字段加亮的方式为用户提供友好的界面
    设计方法开篇
    周末之个人杂想(五)
    ComponentArt对Atlas的集成
    [翻译]使用ASP.NET2.0的ReportViewer查看RDLC报表
    [视频讲解]GridView里做链接实现新闻列表到详细内容页的跳转
    关于正则表达式
    周末之个人杂想(七)

  • 原文地址:https://www.cnblogs.com/yoyoball/p/10146043.html
Copyright © 2011-2022 走看看