2021天梯赛

由于去年参加过比赛,这几天又做了一下vp,相比去年进步了一些。整体来说感觉难度不大,除了最后一题,整体来说拿到250+的分数还是有机会的。

L1总计八道题,100分会语法即可拿满分,完全是手速。
L1-1 人与神 (5 分)
直接输出即可

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout<<"To iterate is human, to recurse divine.";
    return 0;
}

L1-2 两小时学完C语言 (5 分)
按照题意模拟即可

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int x,y,z;
    cin>>x>>y>>z;
    cout<<x-y*z;
    return 0;
}

L1-3 强迫症 (10 分)
接收一个四位数或者试六位数按照题意转换一下格式即可

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    string str;
    cin>>str;
    int x=(str[0]-'0')*10+(str[1]-'0');
    if(str.size()==4)
    {if(x<22){
        if(x>=10)cout<<"20"<<x<<"-"<<str[2]<<str[3];
        else cout<<"200"<<x<<"-"<<str[2]<<str[3];
    } else {
        cout<<"19"<<x<<"-"<<str[2]<<str[3];
    } 
    } else {
        cout<<str[0]<<str[1]<<str[2]<<str[3]<<"-"<<str[4]<<str[5];
    }
    return 0;
}

L1-4 降价提醒机器人 (10 分)
注意一个是整数一个是实数

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int x,w;
    cin>>x>>w;
    vector<double>sd;
    for(int i=0;i<x;i++){
        double k;
        cin>>k;
        if(k<w)sd.push_back(k);
    }
    for(int i=0;i<sd.size();i++){
        auto k=sd[i];
        printf("On Sale! %.1lf\n",k);
    }
    return 0;
}

L1-5 大笨钟的心情 (15 分)
按题意输出即可

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    vector<int>a(24);
    for(int i=0;i<24;i++)cin>>a[i];
    int x;
    while(cin>>x){
        if(x>23||x<0)break;
        cout<<a[x];
        if(a[x]>50)cout<<" Yes\n";
        else cout<<" No\n";
    }
    return 0;
}

L1-6 吉老师的回归 (15 分)
这里建议大家了解一下getline这个函数

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin>>n>>m;
    vector<int>res;
    vector<string>sd;
    // getchar();
    string tt;
    getline(cin,tt);
    for(int i=0;i<n;i++){
        string str;
        getline(cin,str);
        if(str.find("easy")==string::npos&&str.find("qiandao")==string::npos){
            res.push_back(i);
        }
        sd.push_back(str);
    }
    // cout<<res.size()<<"--";
    if(m>=res.size()){
        cout<<"Wo AK le";
    } else {
        cout<<sd[res[m]]<<"\n";
    }
    return 0;
}

L1-7 天梯赛的善良 (20 分)
最大数和最少数的个数如果不会STL的话直接遍历一次记录也可以考验手速

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    map<int,int>mp;
    for(int i=0; i<n; i++){
        int x;
        cin>>x;
        mp[x]++;
    }
    auto k1=mp.begin();
    auto k2=prev(mp.end());
    cout<<k1->first<<" "<<k1->second<<endl;
    cout<<k2->first<<" "<<k2->second<<endl;
    return 0;
}

L1-8 乘法口诀数列 (20 分)
用数组或者vector模拟这个过程就可以了,以为一位数乘以一位数最多会是两位数,判断只需要判断结果大于十还是小于十即可

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,t;
    cin>>n>>m>>t;
    vector<int>a;
    a.push_back(n);
    a.push_back(m);
    int pos=0;
    while(1){
        int k=a[pos]*a[pos+1];
        if(k<10)a.push_back(k);
        else {
            a.push_back(k/10);
            a.push_back(k%10);
        }
        pos++;
        if(a.size()>=t){
            break;
        }
    }
    for(int i=0;i<t;i++){
        cout<<a[i];
        if(i!=t-1)cout<<" ";
    }
    return 0;
}

L2稍微有点难度,如果会用set map vector stack可以很快做完留给做L3的时间
L2-1 包装机 (25 分)
按照题意相当于模拟一个不断入栈出栈的过程,了解一个stack可以很容易解决,注意可能会出现的运行错误,空栈时出栈

#include<bits/stdc++.h>
using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    vector<int>a(n);
    vector<string>b(n);
    for(int i=0;i<n;i++){
        cin>>b[i];
    }
    int t;
    // vector<char>res;
    string res;
    stack<char>s;
    while(cin>>t){
        if(t==-1)break;
        if(a[t]>=m)continue;
        if(t==0){
            if(!s.empty()){
                res+=s.top();
                s.pop();
            }
        } else {
            if(s.size()>=k){
                res+=s.top();
                s.pop();
            }
            s.push(b[t-1][a[t]]);
            a[t]++;
        }
    }
    cout<<res;
    return 0;
}

L2-2 病毒溯源 (25 分)
104 的数据量,题目上给出最开始的溯源只有一个,且不存在循环变异,先确定溯源,dfs一次找到最长链是多少在dfs一次把最长链且序号最小的一个输出即可,找最长链是一个典型的dfs加回溯,回溯的时候记录最长的子链并更新,第二次dfs的时候需要排序,排序的大小按照首先链最长其次序号最小即可,当然也可以遍历一遍。

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
vector<int>a[N];
int in[N];
int dep[N];
void dfs(int s){
    if(a[s].size()==0){
        dep[s]=1;
    }
    for(auto k:a[s]){
        dfs(k);
        dep[s]=max(dep[s],dep[k]+1);
    }
}
vector<int>res;
void dfs2(int x){
    sort(a[x].begin(),a[x].end(),[&](int x,int y){
        if(dep[x]!=dep[y]){
            return dep[x]>dep[y];
        } else {
            return x<y;
        }
    });
    res.push_back(x);
    if(a[x].size())dfs2(a[x][0]);
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,t,x;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>t;
        for(int j=0;j<t;j++){
            cin>>x;
            a[i].push_back(x);
            in[x]++;
        }
    }
    int s;
    for(int i=0;i<n;i++){
        if(!in[i]){
            s=i;
            break;
        }
    }
    dfs(s);
    dfs2(s);
    cout<<res.size()<<"\n";
    for(int i=0;i<res.size();i++){
        cout<<res[i];
        if(i!=(int)res.size()-1)cout<<" ";
    }
    return 0;
}

L2-3 清点代码库 (25 分)
把相同的东西放在一起,记录出现的次数,然后把出现次数多的序号小的放在一起,可以用set套vector,然后在写一个结构题重载一下运算符即可

#include<bits/stdc++.h>
using namespace std;
    int n,m;
struct sk{
    int x;
    vector<int>sd;
    friend bool operator< (const sk& a,const  sk &b){
        if(a.x!=b.x)return a.x>b.x;
        for(int i=0;i<m;i++){
            if(a.sd[i]!=b.sd[i])return a.sd[i]<b.sd[i];
        }
    };
};
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    map<vector<int>,int>mp;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        vector<int>a(m);
        for(int j=0;j<m;j++){
            cin>>a[j];
        }
        mp[a]++;
    }
    vector<sk>res;
    for(auto k:mp){
        res.push_back({k.second,k.first});
    }
    sort(res.begin(),res.end());
    cout<<res.size()<<"\n";
    for(int i=0;i<res.size();i++){
        cout<<res[i].x<<" ";
        for(int j=0;j<m;j++){
            cout<<res[i].sd[j];
            if(j!=m-1)cout<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

L2-4 哲哲打游戏 (25 分)
直接按题意模拟即可

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
vector<int>a[N];
int k[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int t;
        cin>>t;
        a[i].resize(t);
        for(int j=0;j<t;j++){
            cin>>a[i][j];
        }
    }
    int now=1;
    k[1]=now;
    for(int i=1;i<=m;i++){
        int opt;
        cin>>opt;
        int w;
        if(opt==0){
            cin>>w;
            now=a[now][w-1];
        } else if(opt==1){
            cin>>w;
            k[w]=now;
            cout<<now<<"\n";
        } else {
            cin>>w;
            now=k[w];
        }
    }
    cout<<now<<"\n";
    return 0;
}

L3-1 森森旅游 (30 分)
交了好多发都是29分。。。如果ACM赛制可能会卡很久 一个经典的图论题,中间多加了一个RMQ的算法相当于两个算法的小综合,首先经过某点的时候可以把钱全部兑换成旅游金,是全部,所以很容易想到从源点建到n的正相边,边权现金,从n到源点的反向边边权旅游金,然后枚举1到n为中转点,因为政策的改变会发生更改所以要记录一下,可以用一个线段树记录然后单点更改,应该也可以用multiset,不断的删除插入。然后这样可以得29分,因为题目保证的是从1可以到n,但是没有保证从1可以到n-1,所以有些城市可能到不了特判一下就可以三十分了,然后单源最短路的dijstra可以自行学习一下,rmq不会的也可以自行学习一下。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
#define ll long long
#define int ll
vector<tuple<int,int>>e[N],r[N];
int dis[N],rt[N];
int sd[N];
bool v[N],f[N];
struct Sgt{
    int w;
}sgt[N<<2];
#define lson (k<<1)
#define rson (k<<1|1)
void pushup(int k){
    sgt[k].w=min(sgt[lson].w,sgt[rson].w);
}
#define mid (l+r>>1)
ll rk[N];
void build(int l,int r,int k=1){
    if(l==r){
        sgt[k].w=rk[l];
        return;
    } 
    build(l,mid,lson);
    build(mid+1,r,rson);
    pushup(k);
}
void update(int l,int r,int pos,int k=1){
    if(l==r){
        sgt[k].w=rk[l];
        return;
    }
    if(pos>mid){
        update(mid+1,r,pos,rson);
    } else {
        update(l,mid,pos,lson);
    }
    pushup(k);
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,q;
    cin>>n>>m>>q;
    for(int i=0;i<m;i++){
        int u,v,w1,w2;
        cin>>u>>v>>w1>>w2;
        e[u].push_back({v,w1});
        r[v].push_back({u,w2});
    }
    for(int i=1;i<=n;i++){
        cin>>sd[i];
    }
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q1,q2;
    q1.push({0,1});
    q2.push({0,n});
    for(int i=0;i<=n;i++)dis[i]=rt[i]=1e18;
    dis[1]=0;
    rt[n]=0;
    while(q1.size()){
        auto [w,u]=q1.top();
        q1.pop();
        if(v[u])continue;
        v[u]=1;
        for(auto [v,t]:e[u]){
            if(dis[v]>dis[u]+t){
                dis[v]=dis[u]+t;
                q1.push({w+t,v});
            }
        }
    }
    while(q2.size()){
        auto [w,u]=q2.top();
        q2.pop();
        if(f[u])continue;
        f[u]=1;
        for(auto [v,t]:r[u]){
            if(rt[v]>rt[u]+t){
                rt[v]=rt[u]+t;
                q2.push({w+t,v});
            }
        }
    }
    //保证可以到n但是不保证可以到i
    for(int i=1;i<=n;i++){
        int w=(rt[i]+sd[i]-1)/sd[i]+dis[i];
        if(rt[i]>=1e18||dis[i]>=1e18){
            rk[i]=1e18;
        } else 
        rk[i]=w;
    }
    build(1,n,1);
    while(q--){
        int x,w;
        cin>>x>>w;
        ll ss=(rt[x]+w-1)/w+dis[x];
        // rk[x]=ss;
        if(rk[x]!=1e18){
            rk[x]=ss;
        }
        update(1,n,x,1);
        cout<<sgt[1].w<<"\n";
    }
    return 0;
}

L3-2 还原文件 (30 分)
暴力搜索了一下三十分,有点无语。。。第一时间想到的是hash数组,然后暴力搜一下,只是先写了个暴力试试就满分了,不太清楚复杂度怎么证明只是单纯的感觉数据很难构造

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int dp[N];
int a[N];
vector<int>e[111];
bool vis[111];
int m,n;
void dfs(int x){
    if(x==n){
        int now=1;
        vector<int>res;
        while(now!=n){
            res.push_back(dp[now]);
            now=e[dp[now]].size()-1+now;
        }
        for(int i=0;i<res.size();i++){
            cout<<res[i];
            if(i!=res.size()-1)cout<<" ";
        }
        exit(0);
    }
    for(int i=1;i<=m;i++){
        bool ok=1;
        if(vis[i])continue;
        for(int j=0;j<e[i].size();j++){
            if(a[x+j]!=e[i][j]){
                ok=0;
                break;
            }
        }
        if(ok){
            vis[i]=1;
            dp[x]=i;
            // cout<<i<<"--";
            dfs(x+e[i].size()-1);
            vis[i]=0;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    cin>>m;
    for(int j=1;j<=m;j++){
        int t;
        cin>>t;
        e[j].resize(t);
        for(int r=0;r<t;r++){
            cin>>e[j][r];
        }
    }
    dfs(1);
    // cout<<0<<"l";
    return 0;
}

L3-030 可怜的简单题 (30 分)
只有一个答案的题目为出题组好评,这样大家就不用罚坐了而是在这里试最后一题的答案qwq,我那时候试的时候1,2,…100… 现在的话可能会试1/2,1/3…1/n…还是有进步的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值