zoukankan      html  css  js  c++  java
  • codeforces 940E Cashback 题解

    一个就像贪心一样的 DP
    思路还是挺巧妙的

    首先由于可以任意分段 对于任何一个长度 (len<k) 的段 这一段是不能够去掉任何一个数的 也就是每一个数都要被统计到答案里 所以要是弄出来这样一个分段就把它拆成 (len) 个长度为 (1) 的段是等价的
    拆了处理更方便

    其次对于长度 (lengeq k) 的段,这里先看长度不为 (k) 的整数倍的段
    我们可以把它分成 一个长度为 (mk)(m) 为满足 (mk<len) 的最大整数)的段和几个长度为 (1) 的段。
    其中长度为 (mk) 的段取所有情况中最优情况 其它用长度为1的段填满
    与上面同理。

    现在我们只剩下长度为 (1) 的段和长度为 (mk) 的段了。
    接下来 观察后者,如果把它分成 (m) 个长度为 (k) 的段 结果一定不会更劣。
    因为去掉的数不会减小,但可能增大。

    所以就分开。

    然后这题就变成把一些数任意分成长度为 (1)(k) 的段,其中每个长度为 (k) 的段的贡献(就是和)为这段的和减去它的最小值,长度为 (1) 的段就是加上这个数本身了。

    然后可以 dp 了 这里大家应该就都会了
    $dp[i] = min(dp[i - 1] + w[i],dp[i - c] + sum(i - c + 1,i) - min{w[i-c+1],...,w[i]}) $

    最小值用线段树实现了

    code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define mid ((l + r) >> 1)
    #define lson (x << 1)
    #define rson ((x << 1) | 1)
    using namespace std;
    typedef long long LL;
    
    LL a[500005] = {0};
    LL val[2000005] = {0};
    
    void build(LL x,LL l,LL r){
    	if(l == r){ val[x] = a[l]; return; }
    	build(lson,l,mid);
    	build(rson,mid + 1,r);
    	val[x] = min(val[lson],val[rson]);
    }
    
    LL query(LL x,LL l,LL r,LL L,LL R){
    	if(L <= l && r <= R) return val[x];
    	LL ret = 0x3f3f3f3f3f3f3f3f;
    	if(L <= mid) ret = min(ret,query(lson,l,mid,L,R));
    	if(R > mid) ret = min(ret,query(rson,mid + 1,r,L,R));
    	return ret;
    }
    
    LL n,c;
    LL dp[500005] = {0};
    LL pre[500005] = {0};
    
    int main(){
    	memset(dp,0x3f,sizeof(dp));
    	cin >> n >> c;
    	for(LL i = 1;i <= n;i ++) cin >> a[i];
    	for(LL i = 1;i <= n;i ++) pre[i] = pre[i - 1] + a[i];
    	// 前缀和求一段的和
        build(1,1,n); // 线段树别忘了build
    	dp[0] = 0;
    	for(LL i = 1;i <= n;i ++){
    		if(i >= c) dp[i] = min(dp[i],dp[i - c] + pre[i] - pre[i - c] - query(1,1,n,i - c + 1,i));
    		dp[i] = min(dp[i],dp[i - 1] + a[i]);
            // dp转移
    	}
    	cout << dp[n] << endl;
    	return 0;
    }
    

    所以样例解释不能信啊

  • 相关阅读:
    sql求两表的并集、交集、非交集、差集、结果集排序
    c# 为什么要使用Array、ArrayList、List?
    C# 实例化的执行顺序(转)
    正则捕获url的?号传值
    mvc5中重命名项目的名称后,出现"找到多个与名为“Home”的控制器匹配的类型"
    微信开发资料
    windows下建立netcore控制台程序,然后传送到centos7下的docker容器里运行
    error MSB3552: Resource file "**/*.resx" cannot be found. [/ConsoleApp1.csproj]
    c# 编译期常量const和运行时常量readonly
    c# 多线程之-- System.Threading Timer的使用
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744196.html
Copyright © 2011-2022 走看看