zoukankan      html  css  js  c++  java
  • CF1580D Subsequence

    Description

    给定一个序列,选择其中 (m) 个数,记下标为 (b) 序列,最大化

    [sum_{i=1}^m ma_{b_i}-sum_{i=1}^m sum_{j=1}^m f(min (b_i,b_j),max (b_i,b_j)) ]

    其中 (f(i,j)) 表示序列 (a) 区间 ([i,j]) 的最小值。

    Solution

    首先应该观察到第一个和式里带了一个 (m),非常不自然,应该是别有用心,所以可以猜测这个式子其实是有其他含义的。

    发现式子可以改写成

    [sum_{i=1}^m sum_{j=i+1}^m (a_{b_i}+a_{b_j}-2 f(min (b_i,b_j),max (b_i,b_j))) ]

    这个权值长得很像树上两点的距离,而发现笛卡尔树恰好满足这个性质。所以建出笛卡尔树然后 (dp) 即可。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    typedef long long ll;
    
    const int N=4e3+7;
    
    struct Node{
        int ls,rs;
    }t[N];
    
    ll dp[N][N];
    int a[N],top=0,st[N],sz[N],n,m;
    
    void dfs(int u){
        sz[u]=1;
        if(t[u].ls){
            dfs(t[u].ls);
            const int v=t[u].ls;
            for(int i=sz[u];~i;i--)
                for(int j=0,rg=min(sz[v],m-i);j<=rg;j++)
                    dp[u][i+j]=max(dp[u][i+j],dp[u][i]+dp[v][j]+1ll*j*(m-j)*(a[v]-a[u]));
            sz[u]+=sz[v];
        }
        if(t[u].rs){
            dfs(t[u].rs);
            const int v=t[u].rs;
            for(int i=sz[u];~i;i--)
                for(int j=0,rg=min(sz[v],m-i);j<=rg;j++)
                    dp[u][i+j]=max(dp[u][i+j],dp[u][i]+dp[v][j]+1ll*j*(m-j)*(a[v]-a[u]));
            sz[u]+=sz[v];
        }
    }
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++){
            a[i]=read(); int ret=0;
            while(top&&a[st[top]]>=a[i])
                ret=st[top--];
            if(ret) t[i].ls=ret;
            if(top) t[st[top]].rs=i;
            st[++top]=i;
        }
        dfs(st[1]); printf("%lld",dp[st[1]][m]);
    }
    
  • 相关阅读:
    apache安装遇到的问题
    babel+gulp实时转码ES6
    highcharts点击切换,不能自适应宽度
    多行文本溢出
    文件上传
    iscroll最后一个列表项无法显示出来
    curry化函数
    zepto中animate方法的使用注意
    js去除中间空格
    JS实现计算任意一个数的各个位数的和
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15390314.html
Copyright © 2011-2022 走看看