Educational Codeforces Round 95 (Rated for Div. 2) A - D 解题报告

题目链接


A. Buying Torches

思路:

直接计算出需要的木棍,然后取除以 \((x -1)\)(向上取整),最后在加上 \(k\) 即可。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-14 22:22:07
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-15 02:03:23
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

template<class T>
inline void read(T &x){
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    x = x * f;
}

template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }


int main(){

    int t; read(t);
    while(t --){
        ll x, y, k; cin >> x >> y >> k;
        ll all = k * y + k - 1;
        ll tmp = all / (x - 1);
        if(all % (x - 1)) tmp ++;
        tmp += k;
        cout << tmp << endl;
    }
    
    return 0;
}

B. Negative Prefixes

思路 :

直接计算出和 \(sum\)

  • \(sum < 0\) :说明 \(k = n\),直接输出原数组即可。
  • \(sum \geq 0\) :说明第 \(n\) 位是 \(\geq 0\) 的,那么我们要 \(n - 1\) 位也尽量 \(\geq 0\),那么就要把可变动的数里最小的放在当前位(如果当前位是可变的),依次类推,直到 \(sum < 0\)

注:其实就是把可改变的数拿来排序,然后从大到小依次填充。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-14 23:01:26
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-15 02:10:22
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

template<class T>
inline void read(T &x){
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    x = x * f;
}

template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }

const int N = 110;

int a[N], vis[N], b[N];

int main(){

    int t; read(t);
    while(t --){
        int n; read(n);
        ll sum = 0;
        int cnt = 0;
        for(int i = 1; i <= n; i ++) read(a[i]);
        for(int i = 1; i <= n; i ++) read(vis[i]);
        for(int i = 1; i <= n; i ++) sum += a[i];
        for(int i = 1; i <= n; i ++) if(vis[i] == 0) b[++cnt] = a[i];
        sort(b + 1, b + cnt + 1);
        int idx = 0;
        if(sum < 0){
            for(int i = 1; i <= n; i ++) printf("%d ", a[i]);
            puts("");
        } else{
            for(int i = n; i >= 1; i --){
                if(sum < 0) break;
                if(vis[i] == 1){
                    sum -= a[i];
                    continue;
                } else{
                    a[i] = b[++idx];
                    sum -= a[i];
                    vis[i] = 1;
                }
            }
            for(int i = 1; i <= n; i ++){
                if(vis[i] == 0) a[i] = b[++idx];
                printf("%d ", a[i]);
            }
            puts("");
        }
    }
    return 0;
}

C. Mortal Kombat Tower

思路:

首先很容易想到的是:如果第一位是 \(1\),那么答案加一。

那么还有什么情况是一定要跳过 \(1\) 的呢?考虑:\(111\) 这种情况,我们最多打死两个怪物,那么朋友必须要面对一只 \(hard\) 的怪物,所以答案加一。

而对于其他情况:\(000, 001, 010, 011, 100, 101, 110\) ,我们的朋友都是可以避免 \(1\) 的。

所以只要统计下 \([2, n]\) 的区间内存在几个 \(111\) 即可,特判第一位。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-14 23:28:28
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-14 23:38:37
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

template<class T>
inline void read(T &x){
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    x = x * f;
}

template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }

const int N = 2e5 + 10;

int a[N];

int main(){

    int t; read(t);
    while(t --){
        int n; read(n);
        for(int i = 1; i <= n; i ++) read(a[i]);
        int ans = 0, cnt = 0;
        if(a[1] == 1) ans ++;
        for(int i = 2; i <= n; i ++){
            if(a[i] == 1) cnt ++;
            else cnt = 0;
            if(cnt == 3) {
                ans ++;
                cnt = 0;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

D. Trash Problem

思路:

可以向天再借五百年就好了

显然最后合并的两堆的距离最远。

设:\(a, b, c, d\)\((a:最左边的,b:合并完的某一堆,c:合并完的某一堆,d:最右边的)\)

那么 \(ans = b - a + d - c = d - a - (c - b)\)

即最右边的减去最左边的,再减去相邻距离最远的。

那么用两个 \(set\) 来维护信息,\(s_1\) 维护当前的所有坐标,\(s_2\) 维护相邻两堆的距离。

对于每次插入或删除的数,找出其在 \(s_1\) 的前驱和后继,然后更新 \(s_2\) 即可。

注:

  • \(s_2\) 必须是一个 \(multiset\)
  • 找前驱和后继注意处理边界
代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-15 00:13:17
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-15 01:58:19
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

template<class T>
inline void read(T &x){
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    x = x * f;
}

template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }

multiset<ll> s1, s2;


int main(){

    int n, q; read(n); read(q);

    auto add = [&](ll x){
        auto it = s1.lower_bound(x);
        if(it != s1.end()) s2.insert(*it - x);
        if(it != s1.begin()) s2.insert(x - *prev(it));
        if(it != s1.end() && it != s1.begin()) s2.erase(s2.find(*it - *prev(it)));
        s1.insert(x);
    };

    auto del = [&](ll x){
        s1.erase(x);
        auto it = s1.lower_bound(x);
        if(it != s1.end()) s2.erase(s2.find(*it - x));
        if(it != s1.begin()) s2.erase(s2.find(x - *prev(it)));
        if(it != s1.end() && it != s1.begin()) s2.insert(*it - *prev(it));
    };

    auto calc = [&]() -> ll {
        if(sz(s1) <= 2) return 0;
        return *prev(s1.end()) - *s1.begin() - *prev(s2.end());
    };
    
    for(int i = 1; i <= n; i ++){
        ll x; read(x);
        add(x);
        //printf("sz(s2) = %d\n", sz(s2));
    }
    printf("%lld\n", calc());
    

    while(q --){
        int op; read(op);
        ll x; read(x);
        if(op == 1) add(x);
        else del(x);
        printf("%lld\n", calc());
    }
    return 0;

}
posted @ 2020-09-15 02:30  nonameless  阅读(393)  评论(0编辑  收藏  举报