挖土机杯总结

2022-10-16 21:56:55 星期日

https://www.luogu.com.cn/contest/87102

前言

本次时J组课程最后一次模拟赛,题目难度略低,思维能力考察灵活,还有代码能力
对于这一次T1,30多分钟AC,感觉慢了,T2考试没想,T3想出来结果代码不会,T4没时间

T1

T1就是一个模拟分数的运算,需要考察gcd和lcm,考试时我因为没写草稿模拟程序运行结果浪费10多分钟调试,还好对了,考试T1一定要细心,细心,细心,一定要找一些数据自己模拟,对拍。

T2

考试时没想出,其实暴力就可以70了,把每个精灵坐标按R1<R2<R3排序,这样去暴力枚举每个精灵最大值,并且更新总体最大值。满分AC就要减小枚举量。题目中有一个数学公式特别重要,决定了声望最大值来源,其实就是把文字提示换成数学,想不到思路一定要看看题目中的公式之类考虑特殊性质,本题特殊性质就是当俩个坐标一样时,声望取值只跟不同那个有关系,又因为R1<R2<R3不难想到排序一次,把a大的排前提前是b,c相同,我们就可以保证第i个所可以合并的必定在他前面,这样再去求出最大值即可。
代码:

点击查看代码
#include<bits/stdc++.h>
#define N 500050
using namespace std;
int n,r[4],maxnum1=-1,maxnum2=-1,maxn1=-1,maxn2=-1;
struct node{
	int a,b,c,num;
}x[N];
int sw(int w){
	return pow(w,3)/4;
}

bool cmp(node a,node b){
	if(a.b!=b.b) return a.b<b.b;
	if(a.c!=b.c) return a.c<b.c;
	return a.a>b.a;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d%d%d",&r[1],&r[2],&r[3]);
		sort(r+1,r+1+3);
		x[i].a=r[1],x[i].b=r[2],x[i].c=r[3],x[i].num=i;
		if(maxn1<x[i].a){
			maxn1=x[i].a;
			maxnum1=x[i].num;
		}
	}
	sort(x+1,x+1+n,cmp);
	for(int i=2;i<=n;++i){
		if(x[i].b==x[i-1].b&&x[i].c==x[i-1].c){
			int k=min(x[i].a+x[i-1].a,min(x[i].b,x[i].c));
			if(k>maxn2) maxn2=k,maxnum2=i;
		}
	}
	if(maxn1>maxn2){
		cout<<0<<endl<<maxnum1<<endl<<sw(maxn1)<<endl;
	}
	else{
		cout<<1<<endl<<x[maxnum2].num<<" "<<x[maxnum2-1].num<<endl<<sw(maxn2);
	}
	return 0;
}

T3

T3正解为贪心,这个贪心我们画一条数轴,对于每个点都是k,类似补作业,肯定是把今天截至的先写完,所以贪心就是把d天必须消灭的优先消灭,思路不难,代码能力不太好,本题我卡在怎么优先处理今天必须完成的。其实很简单,今天必须完成的就是昨天剩下的,只要我们把昨天遍历一次先修改就好了。
代码

点击查看代码
#include<bits/stdc++.h>
#define maxn 300030
using namespace std;
int n,k,ans,endd;

struct node{
	int d,m;
}e[maxn];
vector <node> a[maxn];
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;++i){
		scanf("%d%d",&e[i].d,&e[i].m);
		a[e[i].d].push_back(e[i]);
		endd=max(endd,e[i].d);
	}
	for(int i=1;i<=endd+1;++i){
		int sum=0;
		for(auto &t : a[i]) sum+=t.m;
		for(auto &t : a[i-1]) sum+=t.m;
		sum=min(k,sum);ans+=sum;
		for(auto &t : a[i-1]){
			int sum1=min(t.m,sum);
			t.m-=sum1,sum-=sum1;
		}
		for(auto &t : a[i]){
			int sum1=min(t.m,sum);
			t.m-=sum1,sum-=sum1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

T4

正解为桶排,这个确实没有想到,这一题加深了我对于桶排序使用理解。
对于柱子我们枚举可以组成的高度,把每一个高度组成都算一遍,如高度为h的柱子可能由h-1和1,h-2和2......最后从大到小排一次,最大的便是组成柱子最多数量,枚举可能的h高度,选用最小的柱子h2到最大柱子h2。
代码:

点击查看代码
#include<bits/stdc++.h>
#define maxn 6060
using namespace std;
int n,cnt[maxn],ans[maxn],minn=1e9,maxx=-1,sum=1;//sum记得初始化为1,至少有一个 

bool cmp(int a,int b){
	return a>b;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		int a;
		scanf("%d",&a);
		cnt[a]++;
		minn=min(a,minn);
		maxx=max(a,maxx);
	}//桶排序 
	for(int i=minn*2;i<=maxx*2;++i){
		for(int j=1;;j++){
			if(j>i-j) break;
			if(i-j==j) ans[i]+=cnt[j]/2;
			else{
				ans[i]+=min(cnt[j],cnt[i-j]);
			}
		}
	}//枚举每一个可能的h是由怎么组成的 
	sort(ans+1,ans+1+maxx*2,cmp);
	cout<<ans[1]<<" ";
	for(int i=2;i<=maxx*2+1;++i){
		if(ans[i]!=ans[i-1]) break;
		sum++;
	}
	cout<<sum<<endl;
	return 0;
}
posted @ 2022-10-17 20:33  啊梓  阅读(40)  评论(0编辑  收藏  举报