zoukankan      html  css  js  c++  java
  • CF1442D Sum

    (n)个栈,每个栈中有若干个带非负价值的物品。每次可以取出栈顶的物品,要求取出恰好(k)个物品,最大化物品的价值和。

    价值满足:(a_{i,j}le a_{i,j+1})

    (n,kle 3000)

    (sum |a_i|le 10^6)


    结论:最优解至多有一个选了一些但没有选完的栈。

    证明:考虑有两个这样的栈,记最后一个为(a_{1,last_1})(a_{2,last_2}),如果(a_{1,last_1}le a_{2,last_2}),因为(a_{2,last_2+1}ge a_{2,last_2}),不选(a_{1,last_1})(a_{2,last_2+1})更优。

    考虑暴力:枚举哪个栈选了但没有被选完,然后对另外(n-1)个栈做01背包。时间复杂度(O(n^3))

    可以优化,分治,记dp数组表示区间外的栈的补集。进入左儿子前,备份一下,然后枚举右区间的每个数,分别(O(k))地更新一下dp数组。

    由于每个栈对dp数组的贡献次数为(O(lg n)),所以时间(O(n^2lg n))


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define N 3005
    #define ll long long
    int n,K;
    vector<int> a[N];
    ll sum[N];
    //void merge(ll c[],ll a[],ll b[]){
    //	memset(c,0,sizeof(ll)*(K+1));
    //	for (int i=K;i>=0;--i)
    //		for (int j=i;j>=0;--j)
    //			c[i]=max(c[i],a[j]+b[i-j]);
    //}
    void upd(ll f[],int w,ll v){
    	for (int i=K;i>=w;--i)
    		f[i]=max(f[i],f[i-w]+v);	
    }
    ll f[15][N];
    ll ans;
    void divide(int k,int l,int r){
    	if (l==r){
    		ll s=0;
    		for (int i=0;i<a[l].size();++i){
    			ans=max(ans,f[k][K-i]+s);	
    			s+=a[l][i];
    		}
    		ans=max(ans,f[k][K-a[l].size()]+s);
    		return;
    	}
    	int mid=l+r>>1;
    	memcpy(f[k+1],f[k],sizeof(ll)*(K+1));
    	for (int i=mid+1;i<=r;++i)
    		upd(f[k+1],a[i].size(),sum[i]);
    	divide(k+1,l,mid);
    	memcpy(f[k+1],f[k],sizeof(ll)*(K+1));
    	for (int i=l;i<=mid;++i)
    		upd(f[k+1],a[i].size(),sum[i]);
    	divide(k+1,mid+1,r);
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d%d",&n,&K);
    	for (int i=1;i<=n;++i){
    		int t;
    		scanf("%d",&t);
    		for (int j=0;j<t;++j){
    			int x;
    			scanf("%d",&x);
    			a[i].push_back(x);
    		}
    		while (a[i].size()>K)
    			a[i].pop_back();
    		for (int j=0;j<a[i].size();++j)
    			sum[i]+=a[i][j];	
    	}
    	divide(0,1,n);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    BIEE建模参考规范
    informatica 学习日记整理
    Web Service 的工作原理
    Oracle 时间差计算
    oracle基础知识
    Oracle 外连接和 (+)号的用法
    根据appId匹配项目名称
    vue技术分享-你可能不知道的7个秘密
    echarts3 迁徙图 迁入迁出
    ES6学习笔记
  • 原文地址:https://www.cnblogs.com/jz-597/p/13919503.html
Copyright © 2011-2022 走看看