ABC-373 A-E题解

比赛链接

A - September 

题目及范围:

思路:

读入每一个字符串,判断字符串长度和当前字符串的出现的次序是否一致即可。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define int long long
#define endl '\n'
//
using namespace std;
int n,m,t,p,k,q;
int num[200005];

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    string s;
    int cnt=0;
    for(int i=1;cin>>s;i++){
        if(s.length()==i) cnt++;
    }
    cout<<cnt<<endl;
}

B - 1D Keyboard

题目及范围:

思路:

暴力枚举当前要按的字母,每次遍历一边键盘。找到要按的字母和上一个字母的距离,累加一下输出。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define int long long
#define endl '\n'
//
using namespace std;
int n,m,t,p,k,q;
int num[27];

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    string s;
    for(int i=1;i<=26;i++) num[i]=i;
    cin>>s;
    int cnt=0;
    bool flag=false;
    int lastj=0;
    for(int i=0;i<26;i++){
        for(int j=0;j<s.length();j++){
            if((s[j]-'A')==i){
                if(flag) {cnt+=abs(j-lastj),lastj=j;break;}
                else {flag=true,lastj=j;break;}
            }
        }
    }
    cout<<cnt<<endl;
}

C - Max Ai+Bj

题目及范围:

思路:

遍历两个数组,找到两个数组中的最大值,相加直接输出即可。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define int long long
#define endl '\n'
//
using namespace std;
int n,m,t,p,k,q;
int num[27];

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n;
    int max1=-0x3f3f3f3f3f3f3f3f;
    int max2=-0x3f3f3f3f3f3f3f3f;
    for(int i=1;i<=n;i++){
        int a;
        cin>>a;
        max1=max(max1,a);
    } 
    for(int i=1;i<=n;i++){
        int a;
        cin>>a;
        max2=max(max2,a);
    }
    cout<<max1+max2<<endl;
}

D - Hidden Weights

题目及范围:

思路:

依题意建图,但注意要建双向边。然后设起点为0,进行bfs。每搜索到一个点,就给这个点根据这个边的权值,赋予满足起点终点关系的权值。bfs每个点只会搜到一次,不用担心冲突。还有就是,考虑到这个图可能是非连通图,记得每个点为起点尝试bfs一遍。如果这个点从未访问过就以该点为起点搜索。保证每个点只会被访问一次。

复杂度O\left ( N \right )

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define int long long
#define endl '\n'
//
using namespace std;
int n,m,num_edge=0;
int head[2000005];
int val[2000005];
bool vis[2000005];

struct Edge{
    int from,to,dis;
    int next;
}edge[2000005];

void add(int from,int to,int dis){//建图
    edge[++num_edge].from=from;
    edge[num_edge].to=to;
    edge[num_edge].dis=dis;
    edge[num_edge].next=head[from];
    head[from]=num_edge;
}

void bfs(int start){//bfs
    queue<int> q;
    vis[start]=true;
    val[start]=0;
    q.push(start);
    while(!q.empty()){
        int u=q.front();
        //cout<<u<<"***"<<val[u]<<endl;
        q.pop();
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(vis[v]==false){
                vis[v]=true;
                val[v]=val[u]+edge[i].dis;
                q.push(v);
            }
        }
    }
}

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,-c);//一定要建双向边并且记得赋相反的权值。
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==false) bfs(i);//每个点都要记得尝试一遍
    }
    for(int i=1;i<=n;i++) cout<<val[i]<<" ";
}

E - How to Win the Election

题目及数据范围:

思路:

对每位候选者来说,拿到的票越多,越容易当选。这种具有单调性的问题考虑二分。

我们先排序以便计算。那么二分的check,实际上就是检查票数在除去当前候选人本身的前M个候选人,能不能全部达到A_{i}+mid+1这个临界票数。如果暴力处理M个人,那么复杂度为O\left ( N*logK*M \right ),超出题目的范围。所以直观考虑优化check的复杂度。

我们可以先给Ai加上mid。再看看它在原数组中的排位。用二分查找降低复杂度。再去判断,排名除了他自己的前M人中,排名比自己低的人,用上剩余的票能不能让排名超过自己。如果可以则自己无法当选,mid增加。反之mid减小。(因为排名比自己高的人不需要再拿剩余的票,所以贪心地给那些排名靠后的人就好了)

该操作用前缀和优化即可。

这个check操作的复杂度在二分查找。所以总复杂度在O\left ( N*logK*logM \right )

代码:

以后再补。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值