挖土机杯总结
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;
}