Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics) 题解

本文通过四道算法题目探讨了不同的问题解决方案,包括寻找最短跳跃路径、确定传球策略、计算曼哈顿距离的奇数和以及验证整数数组的合法性。文章详细分析了解题思路,并提供了AC代码实现,有助于提升读者的算法理解和编程技巧。
摘要由CSDN通过智能技术生成

A. Game

  • 思路
    • 只能跳一次!!!!
    • 从左和从右开始找到第一个0,然后相减+2(从0回到上一格的1陆地)即可
  • 经验教训
  • AC代码

#define int long long
const int maxn = 2e5 + 10;
int a[maxn];

void solve(){
    int n;cin>>n;
    int ans = 0;
    int flagz = 0;
    for (int i = 1; i <= n; ++i) {
        int x;cin>>x;
        a[i] = x;
        if (x==0) flagz = 1;
    }
    int right = 0,left = 0;
    if (flagz==0) cout<<0<<'\n';
    else{
        for (int i = n; i > 1 ; --i) {
            if (a[i]==0) { right = i+1;break;}
        }
        for (int i = 1; i <= n; ++i) {
            if (a[i]==0){
                left = i-1;break;
            }
        }
        cout<<right-left<<'\n';
    }
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;cin>>t;
    for (int i = 0; i < t; ++i) {
        solve();
    }

}

B. Game of Ball Passing

  • 思路
    • 直接贪心,如果传球次数最多的那个人传球的数量比其他所有人的数量之和都多,他就一定得传空球(他传给别人别人不传给他),其他情况都可以一个球互相传解决
  • 经验教训
  • AC代码

#define int long long
const int maxn = 2e5 + 10;
int a[maxn];

bool cmp(int aa,int bb){
    return aa>bb;
}
int dp[maxn];
void solve(){
    int n;cin>>n;
    int flagz = 0;
    int sum = 0;
    int maxx = 0;
    for (int i = 0; i < n; ++i) {
        int x;cin>>x;
        a[i] = x;
        sum+=x;
        maxx = max(maxx,x);
        if (x!=0) flagz = 1;
    }
    if (!flagz) { cout << 0 << '\n';return; }
    if (maxx > sum-maxx){cout<<maxx-(sum-maxx)<<'\n';}
    else cout<<1<<'\n';
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;cin>>t;
    for (int i = 0; i < t; ++i) {
        solve();
    }

}

C. Weird Sum

  • 思路
    • 分行和分列考虑,假设颜色ci只出现在第1行,第5行,第6行,第9行,那么只考虑x的曼哈顿距离就是(5-1+6-1+9-1)+(6-5+9-5)+(9-6),这一段逻辑对应代码的第11-20行
    • 接下来考虑如何得到每一种颜色出现在的行和列,我们预先定义vector row[maxn],row【k】这个vector里面存放的是每个k出现的行数(如果第x行出现了2的k,那就会有两个x,不矛盾)我们在读入数据的时候,读到一个ck,就将它对应的行row【ck】中,列同理。
    • 接下来只需对1-100000的i对应的row【i】和col【i】进行代码11-20行对应操作即可
  • 经验教训
  • AC代码
#define int long long
const int maxn = 1e5 + 10;

vector<int> row[maxn];
vector<int> col[maxn];

int count(vector<int> &color){
    sort(color.begin(),color.end());
    int sum = 0;
    int sz = color.size();
    for (int i = 1; i < sz; ++i) {
        sum+=color[i];
    }
    int n = sz-1;
    int ans = 0;
    for (int i = 0; i < sz-1; ++i) {
        ans += (sum-(n*color[i]));
        sum -= color[i+1];
        n--;
    }
    return ans;
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n,m;
    cin>>n>>m;
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=m ; ++j) {
            int x;cin>>x;
            row[x].push_back(i);
            col[x].push_back(j);
        }
    }
    int ans = 0;
    for (int i = 1; i <= 100000 ; ++i) {
        ans+=(count(row[i])+ count(col[i]));
    }
    cout<<ans;

D. Integral Array

  • 思路
    • 对于数组中出现的某个i,如果【ij,ij+i-1】中的数出现在了数组中,且j并没有出现在数组中,那么数组非法
    • 只需要第一层for遍历i,第二层遍历合法j(i*j≤c的j即为合法j),查看是否出现不合法情况即可
  • 经验教训
  • AC代码
#define int long long
const int maxn = 1e6 + 10;

inline void solve() {
    int n, c;
    cin >> n >> c;
    vector<int> sum(c+1);
    vector<int> cnt(c+1);
    int flago = 0;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        if (x == 1) flago = 1;
        cnt[x]++;
    }
    if (!flago) {
        cout << "NO" << '\n';
        return;
    }
    for (int i = 1; i <= c; ++i) {
        sum[i] = sum[i - 1] + cnt[i];
    }

    for (int i = 1; i <= c; ++i) { // a[i]是选定的某个数
        if (!cnt[i]) continue;
        int num = c / i; // num是所有合法的倍数
        for (int j = 2; j <= num; ++j) { // j是倍数
            int right = min(c, i * j + i - 1);
            int left = i * j;
            if (sum[right] - sum[left - 1] > 0 && cnt[j] == 0) {
                cout << "NO" << '\n';
                return;
            }
        }
    }
    cout << "YES" << '\n';
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin >> t;
    for (int i = 0; i < t; ++i) {
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值