记录土豆片做出来的第一个cf1200分题!!!(Codeforces Round 799 (Div. 4)E. Binary Deque)

作为小菜鸡的土豆片一直都是连800分的题都不一定写的出来,但是!这次土豆片竟然自己a了一道1200分的题(虽然可能是因为还是水题)!值得纪念!链接


题目:

样例: 


土豆片的ac之路:

开始动脑思考:

要找最小操作数,也就是删除的最小个数,要删除尽量少的元素使数组元素总和达到s(目标总和)。

那么该如何实现捏?

土豆片的传统艺能——暴力!遍历出数组子集和等于s并且使子集的长度最大!

但是土豆片吸取了上次被白熊嘲笑的教训,看了看数据范围,好!2e5,暴力直接完蛋。

进一步思考:

题目与数组和数组子集和有关,自然能想到一个好用的东西——前缀和!!!

只需要找到预处理一下每个子集的和,特判总和小于s无解和等于s为0的情况,遍历找到最长的长度,最后用数组总长度减去子集最长的长度即可得到答案!

以下是代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
int n,s;
int a[200005],b[200005];
 
void bluechips(){
	cin>>n>>s;
	int ans=0,num=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i]+b[i-1];
	}
	
	if(b[n]<s){
		cout<<"-1"<<endl;
		return ;
	}
	if(b[n]==s){
		cout<<"0"<<endl;
		return ;
	}
	for(int l=1;l<=n;l++){
		for(int r=2;r<=n;r++){
			if(b[r]-b[l-1]==s){
				num=r-l+1;
				ans=max(ans,num);
			}
		}
	}
	cout<<n-ans<<endl;
	
}
 
signed main(){
	int t;
	cin>>t;
	while(t--){
		bluechips();
	}
	
	
	return 0;
}

输入样例后结果:

 


完美!显然正确!土豆片自信a一发!

 

好!很好!又超时了!土豆片开始忧郁.......

最终实现: 

在椒盐粉的安慰下,土豆片重拾信心再次开始尝试......

土豆片发现,使用了前缀和以后依然没有改变他使用暴力来找最长子集的事实,所以就应该从查找方式上进行修改,聪明的土豆片想到了双指针,或者二分两种方法。

经过仔细考虑,土豆片决定使用双指针来解决这个问题(要是用二分得换种方法写土豆片显然懒得干这种事)。

直接使用双指针来寻找保留部分的最大值!

#include <bits/stdc++.h>
#define int long long
using namespace std;
int  a[200005];
 
void bluechips()
{
    int n,k;
    cin>>n>>k;
    int sum = 0;
    for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
        
 
    if(sum < k)
    {
        cout<<"-1"<<endl;;   //特判
        return;
    }
 
    int res=0;
    int t=0;
    for(int j=1,i=1;j<=n;j++)
    {
        t+=a[j];
        while(i<j&&t>k){
			t-=a[i++];   //灵魂双指针
		}
        if(t==k){
			res=max(res,j-i+1);  //直接找到最大值
		}
    }
 
    cout<<n-res<<endl;  //输出结果
}
 
signed main()
{
	int t;
    cin>>t;
    while(t--)
        bluechips();
 
    return 0;
}

本着样例过了就是过了的原则(忘了是谁教的了)自信提交!

 

完结撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。 


总结: 

1.注意时间复杂度,在想到暴力做法时想办法优化。

2.双指针跟二分的搜索方法要进一步熟悉,多用提高熟练。

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bluechips·zhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值