专栏文章

用暴力写贪心

个人记录参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mir1neqc
此快照首次捕获于
2025/12/04 14:17
3 个月前
此快照最后确认于
2025/12/04 14:17
3 个月前
查看原文

写了依托的贪心

csps T1 的解法多数用了贪心或者求众数,我也一样用了贪心,但是用了结构体,还设了另一个数组来统计,设了个变量来维护,结果打完之后和其他选手讨论 T1 的时候其他选手一脸匪夷所思:这玩意需要用到这个吗?
最后令人忍俊不禁的是,CCF只给它评了 35 分,然而这个代码经过自测是可以 AC 的,要不是复活赛过了真想把 CCF 骂一顿(不对,我 csps 的奖没了,确实该骂)
后面我又去做了些贪心题,发现这种维护思想虽然不是最优解,但是好写,写起来思路也很清晰,个人认为是个不错的做贪心题目的方法。

参考题目

从后往前减,如果不满足干草要求就只加干草数,否则加天数之和,最后一天因为有天数重合,所以额外加 1。
代码如下:
CPP
#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define str string
#define db double

//判断每天是否有干草,有则加 1。 

ll n,t;
ll ans=0;
ll d[200000],b[200000];

int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>t;
	for(int i=1;i<=n;i++){
		cin>>d[i]>>b[i];
	}
	ll cnt=0;
	for(int i=2;i<=n+1;i++){
		if(i==n+1){
			if(t-d[i-1]>=b[i-1]+cnt) ans+=b[i-1]+cnt;
			else ans+=t-d[i-1]+1;
		}
		else{
			if(d[i]-d[i-1]>=b[i-1]+cnt) ans+=b[i-1]+cnt,cnt=0;
			else ans+=d[i]-d[i-1],cnt+=b[i-1]-(d[i]-d[i-1]);
		}
	}
	cout<<ans;
	return 0;
}
这样一来,T1 duel 也可以这样解决,先排序,然后统计数量,往前减,多余的就保留记录多出来的放到下次一起减,少的就照例减,打完后统计每个攻击力的怪兽,最后一起相加即可。
考场写的代码,这里的注释也是我在考场上写的:
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long

// 5
// 1 2 3 1 2
// 3 2 2 1 1
// 2消灭1,3消灭2
// 因此,将攻击力排序,然后令第二小的数减去第一小的数即可
// 桶排序,将攻击力从小到大排序,从后往前减
// 那么问题来了,怎么去设这个贪心?( 
// 5 4 3 2 1        1
// 3 3 3 2 2 1 1    3
// 2 1 1 1 1 1 1    6
// 4 3 3 2 2 2 1    3
// 将小数组减去大数组,剩下的全部相加即可。 

ll n;
ll r;
ll ans=0;
struct node{
	ll s,num;
}a[100050];
bool cmp(node a,node b){
	return a.num>b.num;
}
ll b[100050];
int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	ll p;
	for(int i=1;i<=n;i++){
		cin>>r;
		a[r].s++;
		a[r].num=r;
	}
	sort(a+1,a+1+100000,cmp);
	b[1]=a[1].s;
	for(int i=2;i<=n;i++){
		if(a[i].s){
			if(a[i].s<a[i-1].s+p) p+=a[i-1].s-a[i].s,b[i]=0;
			else b[i]=a[i].s-a[i-1].s-p,p=0;
		}
	}
	for(int i=1;i<=n;i++){
		ans+=b[i];
	}
	cout<<ans;
	return 0;
}
因此实际上写这玩意跟暴力没啥区别(
还是不理解只给 35 分是为什么,甚至不知道怎么水测试点能把这题水到 35 分,太奇怪了

评论

1 条评论,欢迎与作者交流。

正在加载评论...