• CF1580D Subsequence 题解


    Codeforces
    Luogu

    Description..

    给定一个序列 \(\{a_i\}\),选出长度为 \(k\) 的子序列 \(\{a_{b_i}\}\),使得下式最大。

    \[\sum_{i=1}^mma_{b_i}-\sum_{i=1}^m\sum_{j=1}^mF(b_i,b_j) \]

    定义 \(F(i,j)\) 表示 \([\min(i,j),\max(i,j)]\) 中最小值。

    Solution.

    式子可以化成

    \[\sum_{i=1}^m(m-1)c_i-2\sum_{i=1}^m\sum_{j=i+1}^mf(b_i,b_j)\\ \]

    前半段显然直接计算就行了,主要是后半段。
    发现有一个 \(\min\),可以考虑按最值分治,分治处理两端然后合并。
    考虑一个 \(dp_{id,j}\) 表示 \(id\) 这个区间选 \(j\) 个数的最大价值。
    看似总复杂度是 \(O(n^2m)\) 的,但是考虑树上背包复杂度,发现是 \(O(nm)\) 的。
    然后就做完了。

    本质上就是笛卡尔树两点距离和,可以考虑背包

    Coding.

    点击查看代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=4005;int n,m,id;ll a[N],dp[N][N];
    inline void upd(ll &a,ll b) {a<b?a=b:a;}
    inline int solve(int l,int r)
    {
    	if(l>r) return 0;else if(l==r) return dp[++id][1]=a[l]*(m-1),id;
    	int wh=l;for(int i=l+1;i<=r;i++) if(a[i]<a[wh]) wh=i;
    	int ld=solve(l,wh-1),rd=solve(wh+1,r),lz=wh-l,rz=r-wh;id++;
    	for(int i=0;i<=lz;i++) for(int j=0;j<=rz;j++)
    	{
    		upd(dp[id][i+j],dp[ld][i]+dp[rd][j]-2ll*i*j*a[wh]);
    		upd(dp[id][i+j+1],dp[ld][i]+dp[rd][j]+(m-1)*a[wh]-2ll*(i*j+i+j)*a[wh]);
    	}return id;
    }
    int main()
    {
    	read(n,m);for(int i=1;i<=n;i++) read(a[i]);
    	return printf("%lld\n",dp[solve(1,n)][m]),0;
    }
    
  • 相关阅读:
    Thread系列之WaitHandle
    C# lock,Monitor 介绍(多线程并发控制)
    C#多线程学习(五) 多线程的自动管理(定时器)
    Thread系列之AutoResetEvent
    Thread系列之Thread.Sleep(0)
    (转)Java 内存模型
    哈希表(一)
    Java GC
    哈希表(二)
    图(一)
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15428414.html
Copyright © 2020-2023  润新知