码迷,mamicode.com
首页 > 其他好文 > 详细

CF940E Cashback

时间:2020-07-19 16:27:15      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:分析   个数   void   onclick   ++i   ide   而且   lse   uil   

技术图片

 

技术图片

 

技术图片

 

这一段一直在CF上刷DP专项,虽然在考试的时候正解经常还想不出来,但是现在对于一道题仔细想一想n^2,n^3的暴力最起码会写了...... 

分析:刚看到这道题时其实感觉挺玄乎的,自己在纸上写写画画一直也没有什么头绪,后来自己看数据范围强行手弄了一个n^3的暴力,就是定义dp[i]表示序列前i的最优答案,我们就可以枚举断点来进行区间拼接于是有dp[i]=min(dp[i],dp[j]+sum),由于需要O(n)计算前k小,成功的倒在了第七个点的2000的数据下......

对于这道题我们可以想象一下,如果我们有一个长度不足以去除该区间内数字的小数列,那么其实它和将它分为一个一个单独的数字之后的效果是等效的,后者貌似还更好处理,那我们当然要用好处理的来计算,另外,如果我们选择了一个大区间,里面我们可以去除很多的数字,其实我们可以理解为就是每c的长度可以去除里面的一个最小的数字,之后再将相邻的长度为c的序列进行拼接,我们相当于就是向不同长度为c的序列之间填了一些数字,由于数字的大小这些数字对最终答案并没有什么影响,将他们和长度为c的序列分开,让它们单独成为一个序列似乎也可以,而且更好处理,和前面的处理方案相同。这样我们就可以把最终的答案序列理解为若干长度为c的序列和一些单独的点的集合,由于每个区间我们只除去一个数字即可,即最小值,我们就避免了求区间前k小的数字的麻烦,直接用一个线段树维护就可以了(在上午的时候思考如何求前k小卡了我好一阵QAQ),之后我们就可以尝试将区间划分一下,处理出每个区间的最小值,尝试让这些数字的总和最大,我们就可以得到最小的答案了。

技术图片
 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define lson (t<<1)
 4 #define rson (t<<1|1)
 5 #define mid ((l+r)>>1)
 6 using namespace std;
 7 const int N=1e5+10;
 8 int dp[N],a[N];
 9 int b[N];
10 int tree[N];
11 void build(int t,int l,int r){
12     if(l==r){
13         tree[t]=a[l];
14         return;
15     }
16     build(lson,l,mid); build(rson,mid+1,r);
17     tree[t]=min(tree[lson],tree[rson]);
18 }
19 int query(int t,int l,int r,int ql,int qr){
20     if(ql<=l && r<=qr){
21         return tree[t];
22     }
23     if(qr<=mid) return query(lson,l,mid,ql,qr);
24     else if(ql > mid) return query(rson,mid+1,r,ql,qr);
25     else return min(query(lson,l,mid,ql,qr),query(rson,mid+1,r,ql,qr));
26 }
27 int cnt[N],tot;
28 signed main(){
29     int n,c;
30     scanf("%lld%lld",&n,&c);
31     dp[0]=0;
32     for(int i=1;i<=n;++i) scanf("%lld",&a[i]),tot+=a[i];
33     build(1,1,n);
34     int ans=0;
35     for(int i=1;i<=n-c+1;++i)
36         cnt[i+c-1]=query(1,1,n,i,i+c-1);
37     for(int i=c;i<=n;++i)
38         dp[i]=dp[i-c]+cnt[i];
39     for(int i=1;i<=n;++i){
40         dp[i]=max(dp[i],dp[i-1]);
41         if(i>=c) dp[i]=max(dp[i],dp[i-c]+cnt[i]);
42     }
43     printf("%lld\n",tot-dp[n]);
44     return 0;
45 }
View Code

 

CF940E Cashback

标签:分析   个数   void   onclick   ++i   ide   而且   lse   uil   

原文地址:https://www.cnblogs.com/li-jia-hao/p/13339617.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!