2021 昆明 F

Find the Maximum

题链
整理题意发现就是找一个连通块 然后让他的平均绝对值最大
平时的背包都是n2的 显然不能做了
我们考虑猜一些结论
当时我想的就是可能最多不会很多点
比如我们要是次大与最大挨着显然很好
要是离一个点比如 10 1 10 我们拿着显然也很好
要是离两个点比如 10 1 1 10这样显然不如就拿一般好算一点
我们继续想要延长这个比如先是一个大的比如 1e10 0 后面我们得让他吃到好处
就必须大于1e5
1e10 0 1e5+1 1e5+1 我们发现这样就都选下界我们都是只要右边两个就可以了
我们猜测就只有2 3个点再连通块里就可以了
然后对每个点分类讨论一下就可以了

int n,w[N];
double ans=-2e9,res=2e9;
vector<int>g[N];
void dfs(int u,int fa){
    vector<int>a;
    for(auto v:g[u]){
        if(v==fa)continue;
        dfs(v,u);
        a.push_back(w[v]);
    }
    sort(all(a),greater<>());
    int mx1,mx2,mn1,mn2;
    if(a.size())mx1=a[0],mn1=a.back();
    if(a.size()>=2)mx2=a[1],mn2=a[a.size()-2];
    if(a.size()>=2)ans=max(ans,(double)(mx1+w[u]+mx2)/3);
    if(a.size()&&fa)ans=max(ans,(double)(w[fa]+w[u]+mx1)/3);
    if(a.size())ans=max(ans,(double)(w[u]+mx1)/2);
    if(a.size()>=2)res=min(res,(double)(mn1+w[u]+mn2)/3);
    if(a.size()&&fa)res=min(res,(double)(w[fa]+w[u]+mn1)/3);
    if(a.size())res=min(res,(double)(w[u]+mn1)/2);
}
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>w[i];
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    printf("%.8lf",max(ans*ans,res*res)/4);
}
posted @ 2022-11-30 19:23  ycllz  阅读(17)  评论(0)    收藏  举报