• [CF1442D] Sum


    前言

    做过原题的和没做过的都切了,只有我拉了大胯。

    题目

    洛谷

    CF

    讲解

    这道题我在一开始方向就错了,我以为是什么奇技淫巧优化 DP,可以把 (O(nk^2)) 优化成 (O(nk)) 或者 (O(nklog_2k))

    先丢一个结论:

    • 至多存在一个数组没取满。

    证明的话假设有两个没取满,大的那个增多,小的那个减少,显然不劣。典型易证难想结论。

    接下来考虑枚举没取满的那个数组,我们希望得到其它数组的背包结果。

    前后缀拼起来并没有什么用,但是这玩意竟然可以分治!是个人均都会的trick,被开除人籍了

    大概就是你先记录一下当前背包状态,把前半部分背包一下,后半部分丢进去处理。

    出来之后把背包赋值为之前记录的状态,然后把后半部分背包一下,前半部分丢进去处理。

    到最后一层的时候就可以直接更新答案了。

    很牛逼啊,这是 (O(nklog_2n))

    代码

    还没懂看看代码就懂了
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 3005;
    int n,k;
    LL a[MAXN][MAXN],dp[MAXN],tmp[30][MAXN],ans;
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    void solve(int l,int r,int d)
    {
    	if(l == r)
    	{
    		for(int i = 0;i <= a[l][0];++ i) 
    			ans = Max(ans,dp[k-i]+(i == 0 ? 0 : a[l][i]));
    		return;
    	}
    	int mid = (l+r) >> 1;
    	
    	for(int i = 0;i <= k;++ i) tmp[d][i] = dp[i];
    	for(int i = l;i <= mid;++ i)
    		for(int j = k;j >= a[i][0];-- j)
    			dp[j] = Max(dp[j],dp[j-a[i][0]]+a[i][a[i][0]]);
    	solve(mid+1,r,d+1);
    	
    	for(int i = 0;i <= k;++ i) dp[i] = tmp[d][i];
    	for(int i = mid+1;i <= r;++ i)
    		for(int j = k;j >= a[i][0];-- j)
    			dp[j] = Max(dp[j],dp[j-a[i][0]]+a[i][a[i][0]]);
    	solve(l,mid,d+1);
    }
    
    int main()
    {
    //	freopen("factory.in","r",stdin);
    //	freopen("factory.out","w",stdout);
    	n = Read(); k = Read();
    	for(int i = 1;i <= n;++ i)
    	{
    		a[i][0] = Read();
    		for(int j = 1;j <= Min(a[i][0],0ll+k);++ j) a[i][j] = (j == 1 ? 0 : a[i][j-1]) + Read();
    		for(int j = k+1;j <= a[i][0];++ j) Read();
    		a[i][0] = Min(a[i][0],0ll+k);
    	}
    	solve(1,n,0);
    	Put(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    npm install node-echarts npm ERR! code ELIFECYCLE
    MySql-Proxy之多路结果集归并
    Error: Cannot find module 'is-accessor-descriptor'
    如何在Node.js实现兼容ES6
    perl 自动识别编码,转换编码
    Mixin result declared without body
    Python爬虫入门教程 48-100 使用mitmdump抓取手机惠农APP-手机APP爬虫部分
    unexpected token "indent"
    Radware:上周五美国大规模DDoS攻击是如何发生的
    Radware:上周五美国大规模DDoS攻击是如何发生的
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15552082.html
Copyright © 2020-2023  润新知