2021天梯赛解题报告

2021天梯赛题解+总结

L1-1(签到题,略过)

L1-2(输出n-m*k)

L1-3(分情况判断)

L1-4(枚举判断)

L1-5

把所有数都存入数组里面,按下标取然后判断就行了。

L1-6

第一发过了14分就没管,赛后check原代码发现有个bug当时没注意。
注意不能 m = = 0 m==0 m==0时立刻输出,还需要判断一下当前串是否能跳过。
判断串直接用C++中string自带的find函数即可,
注意判断是否到结尾是用 s [ i ] . f i n d ( " q i a n d a o " ) = = s [ i ] . n p o s s[i].find("qiandao")==s[i].npos s[i].find("qiandao")==s[i].npos实现。
代码

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
#define sc(x) scanf("%d",&x);
#define scl(x) scanf("%lld",&x);
#define rp(i,s,t) for(int i=(s);i<=(t);i++)
#define RP(i,s,t) for(int i=(s);i>=(t);i--)
#define outval(x) printf("%d\n",x);
#define outval2(x,y) printf("%d %d\n",x,y);
#define outval3(x,y,z) printf("%d %d %d\n",x,y,z);
#define pY puts("Yes")
#define pN puts("No")
using namespace std;
const int N = 1e5+7;
const int INF = 0x3f3f3f3f;
string s[37];
int main(){
    // freopen("r","in.txt",stdin);
    int n,m;cin>>n>>m;
    getchar();
    rp(i,1,n) getline(cin,s[i]);
    rp(i,1,n){
        if(m==0&&s[i].find("easy")==s[i].npos&&s[i].find("qiandao")==s[i].npos){
            cout<<s[i]<<endl;
            return 0;
        }
        if(s[i].find("easy")==s[i].npos&&s[i].find("qiandao")==s[i].npos){
            m--;
        }
    }
    cout<<"Wo AK le"<<endl;
    return 0;
}

L1-7

先把所有数存进数组里面。
然后就是利用 C + + C++ C++自带的函数直接算出答案。
∗ m i n _ e l e m e n t *min\_element min_element函数找出 v e c t o r vector vector里面的最小值 m i n min min
然后再用 c o u n t count count函数计算 m i n min min的出现次数即可。
最大值同理。

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
inline int read(){
    int s=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*f;
}
const int N = 2e5+7;
int a[N];
void solve(){
    int n=read();rp(i,1,n) a[i]=read();
    int min=*min_element(a+1,a+1+n);
    cout<<min<<" "<<count(a+1,a+1+n,min)<<endl;
    int max=*max_element(a+1,a+1+n);
    cout<<max<<" "<<count(a+1,a+1+n,max)<<endl;
}
int main(){
    //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
    // freopen("in.txt", "r", stdin);
    //debug = 1;
#endif
    //time_t beg, end;
    //if(debug) beg = clock();
    solve();
    /*
    if(debug) {
        end = clock();
        printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
    }
    */
    return 0;
}

L1-8

直接按照题意模拟就行了。
注意一下 a 1 = = 0 a_{1}==0 a1==0或者 a 2 = = 0 a_{2}==0 a2==0的情况。

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
inline int read(){
    int s=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*f;
}
const int N = 2e5+7;
int a[N];
void solve(){
    int a1=read(),a2=read(),n=read();
    vector<int> res;
    int cur0=0,cur1=1;
    res.push_back(a1);
    res.push_back(a2);
    while(res.size()<n){
        int num=res[cur0]*res[cur1];
        if(num==0){
            res.push_back(0);
            cur0++;
            cur1++;
            continue;
        }
        int temp=num;
        vector<int> tt;
        while(temp>0){
            tt.push_back(temp%10);
            temp/=10;
        }
        reverse(tt.begin(),tt.end());
        for(auto val:tt) res.push_back(val);
        cur0++;cur1++;
    }
    rp(i,0,n-1) cout<<res[i]<<(i==n-1?"\n":" ");
}
int main(){
    //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
    // freopen("in.txt", "r", stdin);
    //debug = 1;
#endif
    //time_t beg, end;
    //if(debug) beg = clock();
    solve();
    /*
    if(debug) {
        end = clock();
        printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
    }
    */
    return 0;
}

L2-1

用一个栈来维护筐,一个 v e c t o r vector vector维护流水线。
至于每次过程可以直接用 s t r i n g string string维护轨道,直接调用自带的 e r a s e erase erase函数每次删除第一个字符就行了。
快的方法就可以用一个 d e q u e deque deque来维护轨道,每次操作直接调用 p o p _ f r o n t pop\_front pop_front函数和 f r o n t front front函数即可。
trick:注意如果轨道为空时,按对应按钮时不会强制执行0号键

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define pY puts("YES")
#define pN puts("NO")
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
#define outval2(a,b) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b << "\n";
#define outval3(a,b,c) cout << "Debuging...|" << #a << ": " << a <<"\t"<< #b << ": " << b <<"\t"<< #c << ": " << c << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
inline int read(){
    int s=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*f;
}
const int N = 2e5+7;
deque<char> s[107];
void solve(){
    int N=read(),M=read(),S=read();
    rp(i,1,N){
        rp(j,1,M){
            char ch;scanf("%c",&ch);
            s[i].push_back(ch);
        }
        getchar();
    }
    // rp(i,1,N){
        // for(auto val:s[i]) cout<<val;
        // cout<<endl;
    // }
    stack<char> ss;
    vector<char> res;
    int op;
    while(~scanf("%d",&op)){
        if(op==-1) break;
        if(op==0){
            if(ss.size()!=0){
                res.push_back(ss.top());ss.pop();
            }
        }
        else{
            if(s[op].size()==0) continue;
            if(ss.size()>=S){
                res.push_back(ss.top());
                ss.pop();
            }
            ss.push(s[op].front());
            s[op].pop_front();
        }
    }
    for(auto val:res) cout<<val;
}
int main(){
    //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
    // freopen("in.txt", "r", stdin);
    //debug = 1;
#endif
    //time_t beg, end;
    //if(debug) beg = clock();

    solve();

    /*
    if(debug) {
        end = clock();
        printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
    }
    */
    return 0;
}

L2-2

求树的直径,直接 d f s dfs dfs先搜索出最小的最远端点 p o s pos pos
然后再以 p o s pos pos端点进行 d f s dfs dfs搜索,同时用一个 v e c t o r vector vector维护答案就行了。
注意比较字典序时,需要找到第一个不相等的数,再根据题意判断大于还是小于符合条件。
代码不给了,也比较好写。

L2-3

学长说可以 m a p map map维护 v e c t o r vector vector过。
但是我的这个做法超时了,因此改成了 h a s h hash hash才过。
关于哈希算法不懂的可以参考我的这篇博客:戳我
不过重载比较函数(字典序)时出了点 b u g bug bug,赛后发现了(比赛时第二次出现这个错误了)。

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
#define sc(x) scanf("%d",&x);
#define scl(x) scanf("%lld",&x);
#define rp(i,s,t) for(int i=(s);i<=(t);i++)
#define RP(i,s,t) for(int i=(s);i>=(t);i--)
#define outval(x) printf("%d\n",x);
#define outval2(x,y) printf("%d %d\n",x,y);
#define outval3(x,y,z) printf("%d %d %d\n",x,y,z);
#define pY puts("Yes")
#define pN puts("No")
using namespace std;
const int N = 1e5+7;
const int INF = 0x3f3f3f3f;
const ll mod1 = 1e9+7;
const ll p = 12582917;
map<ll,int> mp;
int n,m;
bool cmp(vector<ll> a,vector<ll> b){
    if(mp[a[m]]!=mp[b[m]]) return mp[a[m]]>mp[b[m]];
    else{
        rp(i,0,m-1){
            if(a[i]<b[i]) return 1;
            else if(a[i]==b[i]) continue;
            else return 0;
        }
    }
}
int main(){
    sc(n);sc(m);
    vector<vector<ll> >res; 
    rp(i,1,n){
        vector<ll> temp;
        rp(j,0,m-1){
            ll x;scl(x);
            temp.push_back(x);
        }
        ll res1=0;
        rp(j,0,m-1) res1=(res1*p%mod1+temp[j])%mod1;
        temp.push_back(res1);
        if(mp.find(res1)==mp.end()) res.push_back(temp);
        mp[res1]++;
    }
    sort(res.begin(),res.end(),cmp);
    cout<<res.size()<<endl;
    for(auto val:res){
        int len=val.size();
        ll res1=0;
        rp(j,0,m-1) res1=(res1*p+val[j])%mod1;
        cout<<mp[res1];
        rp(j,0,m-1) cout<<" "<<val[j];
        cout<<endl;
    }
    return 0;
}

L2-4

题意有点恶心,不过理解后就是一道 n t nt nt题。
算是 L 2 L2 L2中最简单的题,直接按照题意模拟就行了。
代码就不放了,不想再写一遍了。。。

L3-1

经典最短路题,算是比较套路的题目了。
题目要求我们在一个点换了旅游金之后就只能使用旅游金支付,其实就是从这个点到终点花费的最小的旅游金数目。
而我们需要先到这个点,在前面我们只能支付现金,即从起始点到当前点花费的最小现金数目。
所以题目被转换成了从1到i花费的最小现金数+从i到n花费的最小旅游金的数目/汇率(上取整)。
从1到i花费的最小现金数我们可以直接建边(边权为现金),然后跑最短路即可。
而从从i到n花费的最小旅游金的数目相对没这么好求了,
不过也算是最短路的经典问题。
我们可以直接建反图(边权为旅游金),最短路维护的是反图中n->i的花费的最小旅游金数目,即对应原图中i->n花费的最小旅游金的数目。
关于反向建边不懂的话可以参考这篇blog
对于最短路,我们需要用Dijkstra+堆优化维护,
保证时间复杂度为O(nlogn)。
这样我们对于每次查询直接暴力只能拿22分。
然后我们考虑优化。
我们发现每次我们只会修改一个地方的汇率,那么我们就可以用一个map来维护所有点产生的答案以及其个数,一个set来记录所有点产生的答案,每次修改最多会删除一个点(set中的erase函数时间复杂度为logn),每次查询最小值是O(1)的。
总的时间复杂度就是O(nlogn)。
不过这个题会卡常,注意把cin和cout改成printf和scanf就行了。
trick:
1.会出现自环
2.会出现重边

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
#define sc(x) scanf("%d",&x);
#define scl(x) scanf("%lld",&x);
#define rp(i,s,t) for(register int i=(s);i<=(t);i++)
#define RP(i,s,t) for(register int i=(s);i>=(t);i--)
#define outval(x) printf("%d\n",x);
#define outval2(x,y) printf("%d %d\n",x,y);
#define outval3(x,y,z) printf("%d %d %d\n",x,y,z);
#define pY puts("Yes")
#define pN puts("No")
#define p_b push_back
#define m_p make_pair
#define pii pair<int,int> 
#define pil pair<int,ll>
using namespace std;
const int N = 2e5+7;
const int INF = 0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
struct edge{int u,v;ll c,d;}p[N];
vector<pil> G[N];
ll a[N];
ll dis1[N],dis2[N];
int vis[N];
struct node{
    int p;
    ll w;
    friend bool operator < (node a,node b){
        return a.w>b.w;
    }
};
set<ll> ss;
map<ll,int> mp;
int n,m,q;
void Dijkstra1(){
    rp(i,1,n) dis1[i]=LINF,vis[i]=0;
    dis1[1]=0;
    priority_queue<node> q;
    q.push(node{1,dis1[1]});
    while(!q.empty()){
        node t=q.top();q.pop();
        int u=t.p;vis[u]=1;
        ll w=t.w;
        // cout<<u<<" "<<w<<endl;
        for(auto val:G[u]){
            int v=val.first;
            if(!vis[v]&&dis1[v]>val.second+w){
                dis1[v]=val.second+w;
                // cout<<v<<" "<<dis1[v]<<endl;
                q.push(node{v,dis1[v]});
            }
        }
    }
}
void Dijkstra2(){
    rp(i,1,n) dis2[i]=LINF,vis[i]=0;
    dis2[n]=0;
    priority_queue<node> q;
    q.push(node{n,dis2[n]});
    while(!q.empty()){
        node t=q.top();q.pop();
        int u=t.p;vis[u]=1;
        ll w=t.w;
        for(auto val:G[u]){
            int v=val.first;
            if(!vis[v]&&dis2[v]>val.second+w){
                dis2[v]=val.second+w;
                q.push(node{v,dis2[v]});
            }
        }
    }
}
int main(){
    // freopen("in.txt","r",stdin);
    sc(n);sc(m);sc(q);
    rp(i,1,m){
        sc(p[i].u);
        sc(p[i].v);
        scl(p[i].c);
        scl(p[i].d);
    }
    rp(i,1,n) scl(a[i]);
    rp(i,1,m){
        if(p[i].u==p[i].v) continue;
        G[p[i].u].push_back(make_pair(p[i].v,p[i].c));
    }
    Dijkstra1();
    rp(i,1,n) G[i].clear();
    rp(i,1,m){
        if(p[i].u==p[i].v) continue;
        G[p[i].v].push_back(make_pair(p[i].u,p[i].d));
    }
    Dijkstra2();
    // cout<<"test1"<<endl;
    // rp(i,1,n) cout<<i<<" "<<dis1[i]<<endl;
    // cout<<"test2"<<endl;
    // rp(i,1,n) cout<<i<<" "<<dis2[i]<<endl;
    int x;ll aa;
    sc(x);scl(aa);a[x]=aa;
    rp(i,1,n){
        if(dis1[i]==LINF||dis2[i]==LINF) continue;
        ll ans=dis1[i]+1ll*(dis2[i]+a[i]-1)/a[i];
        ss.insert(ans);
        mp[ans]++;
    }
    // for(auto val:ss) cout<<"debug val: "<<val<<endl;
    printf("%lld\n",*ss.begin());
    q--;
    while(q--){
        sc(x);scl(aa);
        if(dis1[x]!=LINF&&dis2[x]!=LINF){
            ll ans=dis1[x]+1ll*(dis2[x]+a[x]-1)/a[x];
            mp[ans]--;
            if(mp[ans]==0) ss.erase(ans);
            a[x]=aa;
            ans=dis1[x]+1ll*(dis2[x]+a[x]-1)/a[x];
            mp[ans]++;
            ss.insert(ans);
        }
        printf("%lld\n",*ss.begin());
    }
    return 0;
}

L3-2

数据很水,直接dfs暴力拿满。
直接贪心取最长串+哈希的话能拿26分,不过是明显的错误做法。
h a c k hack hack数据(学长提供的):
121212
1212
121
正解应该是 a c ac ac自动机+ d p dp dp

L3-3

没有做,不过听说是一道cf上的莫比乌斯反演题改编的。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值