天梯选拔赛2补题_2024_03_09
补题1:奶茶袋收集
题意:

做法:贪心。之前还做过类似的题,赛时一直想不出来。选择k个连续的的区间,就是需要添加k-1个挡板。问题是挡板设置在哪里?可以发现一个连续线段的max-min等于线段中各个差值之和。如果k=1,那么ans=∑(ai+1-ai);如果k=2,那么需要添加一个挡板。贪心地放,挡板应该放在最大的ai+1-ai中。然后答案为剩下的ai+1-ai。
void solve(){ //补L1-7--奶茶袋收集-贪心。之前写过一模一样的题。。现在还想歪了,往前缀和想。。
int n,k,x,ans=0,last=-1;
cin>>n>>k;
vector<int> dif;
for(int i=1;i<=n;i++){
cin>>x;
if(i>=2) dif.emplace_back(x-last);
last=x;
}
sort(dif.begin(),dif.end(),greater<int>());
for(auto d:dif){
if(k>1) k--;
else ans+=d;
}
cout<<ans;
}
补题2:swj学长的融合
题意:

做法:题目本身完全没有难度,主要是读题目没读懂升级机制是什么,不知道怎么样“以此类推”。赛后读懂题目之后轻松补了。
vector<pair<int,int>> vct[100005];
int x,m,a,b,c,d,ans=0;
void dfs(int step){
for(auto to:vct[step]){
ans+=to.second;
dfs(to.first);
}
}
void solve(){ //补L2-2--swj学长的精灵融合--建图dfs..赛时题目都没读懂,不知道等级升级系统(类似金铲铲)是怎么样都,不知道怎么以此类推..
cin>>x>>m;
for(int i=1;i<=m;i++){
cin>>a>>b>>c>>d;
int exp=1;
if(d==1) exp=0;
if(c==1) exp+=( (d-2) * (1+d-2) )/2;
if(c==2) exp+=( (d-2) * (2+2*(d-2) ) )/2;
if(c==3) exp+=( (d-2) * (5+5*(d-2)) )/2;
//cout<<exp<<endl;
vct[a].emplace_back(b,exp);
}
dfs(x);
cout<<ans;
}
补题3:红石难题
题意:

做法:思维(关键)+贪心--把二维坐标轴拉成一条数轴(常有的做法)转换为一维的,之后进行简单贪心即可。
注意的点!:输出的时候如果直接用了ceil,要控制输出小数点,ceil返回的不是整型,输出会带小数点。还有就是特判m=0的情况;
还有最最重要一点!length初始值是1,因为计算的是长度,实际上要的是数轴上端点的个数。而起始点上没有算上的,要自己加上!!!!比如长度为5的数轴,是有6个点的。长度是端点间的间隙,有5个间隙的话,那么需要6个点。
void solve(){ //补L1-5红石难题--思维(关键)+贪心--把二维坐标轴拉成一条数轴(常有的做法)转换为一维的,之后进行简单贪心即可-好题!
//有一个很关键的点!!--红石信号的传导只和他放置的红石顺序有关!--这是可以拉成一条数轴的关键,传递是一维传的,是在一条线上传的.
//一个红石信号源可以让周期d=(15-m)*2+1个红石达到能量m及以上。
//贪心的放。结果需要的红石为;ceil(数轴的长度/d)
int n,m,x,y,length=1,ans;
cin>>n>>m;
int d=(15-m)*2+1;
pair<int,int> last;
for(int i=1;i<=n;i++){
cin>>x>>y;
if(i>=2) length+=abs(last.first-x)+abs(last.second-y);
last={x,y};
}
//ans=length/d+length%d?1:0; //运算顺序问题 wrong!!
//ans=length/d+(length%d?1:0);
ans=ceil(1.0*length/d);
if(m==0) cout<<"0"; //特判
//else cout<<ans;
//else cout<<(int)ceil(1.0*length/d); //ok
//else cout<<ceil(1.0*length/d); //返回值类型不是int,输出会带小数点 wrong!! 加一个fixed<<setprecision(0)才行
else cout<<fixed<<setprecision(0)<<ceil(1.0*length/d);
}
补题4:幸运号码
题意:
做法:状态压缩,这种题也是一种类型吧。类似智乃的36倍数。但是这题还简单一点,不用考虑数字的性质,只要求各位和即可。提前预处理每个数字的位数奇偶和各位之和,存在cnt[2][100]中,便于后面直接从cnt中进行查询符合的个数。
再对每一个数字进行切割处理,用vct储存每一个合法的切法,切完之后所需的那个数值。之后再遍历一次vct里面的数,在cnt中查询符合的个数。全部加起来即是ans.
int ans=0;
int cnt[2][100]; //1奇 0偶--二维为各位之和。预处理好cnt数组,方便查询
vector<pair<int,int>> vct; //存放每个数字剪了之后,需要拼在左边或右边的数值及奇偶性
//这题因为拆位有问题,改了很久。还是不够熟悉,写的不够多,一位一位拆右边的位写的多。一位一位拆左边就明显不够熟练了,出现各种问题而且还没一下意识到错误。导致改了两个小时..
//拆右边的数字是取余'%',拆左边的数字是除法'/'
void solve(){ //补L2-3幸运号码--!!状态压缩!!--字符串!拼接!--对于每一个数字,它可能作为左部出现,也可能作为右部出现.切割的点也可能有多个.
int n,x;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
int digit=0,sum=0,x0=x;
while(x0){
digit++;
sum+=x0%10;
x0/=10;
}
cnt[digit&1][sum]++;
if(digit==1) vct.emplace_back(x,1);
else {
x0=x;
int cnt0=0,leftsum=sum,rightsum=0;
while(leftsum>rightsum){
vct.emplace_back(leftsum-rightsum,digit&1);
leftsum-=x0%10;
rightsum+=x0%10;
x0/=10;
}
//int num=10*(digit-cnt0-1); wa!!!!
int num=pow(10,digit-cnt0-1);
x0=x,cnt0=0,leftsum=0,rightsum=sum; //这里只是一位,不用各位相加!!! 细节!!
bool check=false;
while(rightsum>0&&rightsum>leftsum){ //作为右部和作为左部的代码是不一样的!!细节非常不一样!!!
if(check) vct.emplace_back(rightsum-leftsum,digit&1); //第一个不放入,因为上面已经放入过了..
check=true;
num=pow(10,digit-cnt0-1);
if(num==0) break;
int cursum=0,xx0=x0/num;
while(xx0){
cursum+=xx0%10;
xx0/=10;
}
leftsum=cursum; //作为右部的细节和左部的不一样!!!改了两个小时....
rightsum=sum-cursum;
cnt0++;
//leftsum+=x0/num; //这里还是有问题!!例如22222,22222/1000=22,只是得到了数字,而不是2+2=4;
//rightsum-=x0/num;
}
}
}
for(auto v:vct) ans+=cnt[v.second][v.first];
cout<<ans;
}
补题5:恶心的广告
题意:

做法:赛时没时间看题目,实际上不难。bfs+优先队列即可。
注意的点:不管当前打不打得过,都要放到优先队列里面。优先队列要重载运算符。power小的放在队顶。遇到第一个打不过的就可以break了。
而且如果遇到的是强化剂,应该马上加到ability。怎么重载运算符也是一个点☝️,而且这个是跟平时写的cmp是反着的。return a.power > b.power; 才是小的在堆顶.
//struct pair_hash //unordered_map存放pair需要传入哈希函数
//{
// template<class T1, class T2>
// std::size_t operator() (const std::pair<T1, T2>& p) const
// {
// auto h1 = std::hash<T1>{}(p.first);
// auto h2 = std::hash<T2>{}(p.second);
// return h1 ^ h2;
// }
//};
//unordered_map<pair<int,int>,int,pair_hash> mp;
int n,m,x0,cc,t,ability=-1;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
vector< vector<int> > vct;
map<pair<int,int>,int> mp;
map<pair<int,int>,int> vis;
typedef struct myp{
int xx,yy;
int power;
friend bool operator < (const myp &a,const myp &b){ //重载运算符
return a.power>b.power; //power从小到大排序,和cmp是反着的!!!
}
}myp;
priority_queue<myp> pq;
void solve(){ //补L2-4恶心的广告--赛时连题目都没看,没时间看,也没什么人过这题--赛后一眼bfs+优先队列,写写看...
cin>>n>>m>>x0>>cc>>t;
for(int i=0;i<n;i++){
vector<int> cur;
for(int j=0;j<m;j++){
int z;
cin>>z;
cur.emplace_back(z);
}
vct.emplace_back(cur);
}
for(int i=1;i<=t;i++){
int a,b;
cin>>a>>b;
mp[{a-1,b-1}]=1;
}
myp cur;
cur.xx=x0-1,cur.yy=cc-1,cur.power=vct[x0-1][cc-1];
pq.emplace(cur);
vis[{x0-1,cc-1}]=1; //是x0-1,cc-1,而不是x0,cc
while(pq.size()){
cur=pq.top();
pq.pop();
if(ability==-1) ability=cur.power;
else if(ability>=cur.power&&!mp[{cur.xx,cur.yy}]) ability+=cur.power;
else if(!mp[{cur.xx,cur.yy}]) break;
//有可能出现一种情况就是:到了一个点,上下左右。发现都打不过,再去看别的点,别的点有打得过点,提升了能力。但是已经回不去当时打不过那些点了。
//怎么样在可达都所有点中,把所有都强化剂先拿了,再去打人
//不管打不得过,全部加入到优先队列中,取出来到时候再判!!!--
for(int i=0;i<4;i++){
int x=cur.xx+dx[i];
int y=cur.yy+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&!vis[{x,y}]){
myp zz;
zz.xx=x,zz.yy=y,zz.power=vct[x][y];
pq.emplace(zz);
vis[{x,y}]=1;
if(mp[{x,y}]) ability+=vct[x][y];
}
}
}
cout<<ability;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步