Codeforces Round 938 (Div. 3) A-D题

文章讲述了四个编程竞赛题目,涉及买法策略、矩阵操作、双指针技巧和滑动窗口问题,展示了如何使用不同的算法和数据结构(如map和双指针)来解决这些问题。
摘要由CSDN通过智能技术生成

和舍友打瓦打上头了,游戏结束了才发现有把div3没打,晚了40分钟去打,真是一场酣畅淋漓的掉分啊

A. Yogurt Sale

(A题敲太快wa了一发)
有两种买法:

  • 全用a策略买
  • 全用b策略买
    模拟即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t;
void solve() {
    int n , a , b;
    cin >> n >> a >> b;
    cout << min(n * a , n / 2 * b + n % 2 * a) << endl;
}
signed main() {
    cin >> t;
    while (t--) solve();
}

B. Progressive Square

注意到 a 1 , 1 a_{1,1} a1,1是整个矩阵中最小的元素,所以对b数组进行排序,用map存下数组中每个数。然后在枚举a矩阵,检查b中是否存在对应的数

#include<bits/stdc++.h>
#define int long long
using namespace std;
int t , n , c , d , a[250006];
map<int , int> mp;
void solve() {
    mp.clear();
    cin >> n >> c >> d;
    for (int i = 1;i <= n * n;i++) {
        cin >> a[i];
        mp[a[i]]++;
    }
    sort(a + 1 , a + n * n + 1);
    int s = a[1];
    for (int i = 1;i <= n;i++) {
        for (int j = 1;j <= n;j++) {
            if (!mp[s + (i - 1) * c + (j - 1) * d]) {
                cout << "NO" << endl;
                return;
            }
            mp[s + (i - 1) * c + (j - 1) * d]--;
        }
    }
    //for (int i = 1;i <= n * n;i++) cout << a[i] << " ";
    //cout << endl;
    cout << "YES" << endl;
}
signed main() {
    cin >> t;
    while (t--) solve();
}

C. Inhabitant of the Deep Sea

定义双指针l,r,每次将l,r对应的元素减去 m i n [ a l , a r ] min\left[a_{l},a_{r}\right] min[al,ar],若l,r对应的元素有一个为零,则l++或者r–。
注意判断k为奇数的情况,如果k恰好等于 m i n [ a l , a r ] − 1 min\left[a_{l},a_{r}\right]-1 min[al,ar]1要判断 a l a_{l} al是否恰好被消去。
(记得开long long)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int t , n , a[200005] , k;
void solve() {
    cin >> n >> k;
    for (int i = 1;i <= n;i++) cin >> a[i];
    int l = 1 , r = n , ans = 0 , tt = k;
    while (l < r && k>0) {
        int x = min(a[l] , a[r]);
        a[l] -= x;
        a[r] -= x;
        if (!a[l] && k >= x * 2 - 1) l++ , ans++;
        if (!a[r] && k >= x * 2) r-- , ans++;
        k -= x * 2;
    }
    if (l == r) {
        if (k >= a[l]) ans++;
    }
    cout << ans << endl;

}
signed main() {
    cin >> t;
    while (t--) solve();
}

D. Inaccurate Subsequence Search

只要分别算出加入和消除每个元素的贡献就行,类似于滑动窗口,每次滑动加入下一个数的贡献并且消除窗口末尾的数的贡献,用两个map来维护区间内每个数的个数和目标个数,下面是对 a i a_{i} ai的贡献的计算方式:

  • 正贡献:如果计入后 a i a_{i} ai的个数小于等于目标 a i a_{i} ai的个数,则贡献等于 a i a_{i} ai个数的变化量
  • 负贡献:如果计入前 a i a_{i} ai的个数小于等于目标 a i a_{i} ai的个数,则贡献等于 a i a_{i} ai个数的变化量
    (这里有个比较容易wa的点,就是不能简单的对贡献加一减一,而是要加上变化量)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t , n , m , k , a[200005] , b[200005];
map<int , int> mp , sel;
void solve() {
    mp.clear();
    sel.clear();
    cin >> n >> m >> k;
    for (int i = 1;i <= n;i++) cin >> a[i];
    for (int i = 1;i <= m;i++) {
        cin >> b[i];
        sel[b[i]]++;
    }
    int now = 0 , ans = 0;
    for (int i = 1;i <= m;i++) {
        int t1 = mp[a[i]];
        mp[a[i]]++;
        if (t1 < sel[a[i]]) {
            now += mp[a[i]] - t1;
        }
    }
    if (now >= k) ans++;
    //cout << now << " ";
    for (int i = m + 1;i <= n;i++) {
        int t1 = mp[a[i]] , t2 = mp[a[i - m]];
        mp[a[i]]++;
        mp[a[i - m]]--;
        if (t1 < sel[a[i]]) {
            now += mp[a[i]] - t1;
        }
        if (t2 <= sel[a[i - m]]) {
            now -= t2 - mp[a[i - m]];
        }

        if (now >= k) ans++;
        //cout << now << " ";
    }
    cout << ans << endl;
}
signed main() {
    cin >> t;
    while (t--) solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值