Educational Codeforces Round 97 (Rated for Div. 2)

A. Marketing Scheme

题意;

这道题难在读题,有顾客想要购买数量为 x x x 的猫粮, x x x 属于区间 [ l , r ] [l,r] [l,r],而你会制定一个折扣,相当于购买 a a a 个就会享受折扣,其余的 x m o d    a x \mod a xmoda 则按原价购买。如果 x m o d      a ≥ a 2 x\mod \ a≥\frac{a}{2} xmod a2a,那么顾客会购买多购买使得满折扣,你希望顾客多购买,故请你能否找到一个折扣 a a a,使得顾客总想这样做。

a a a 的值不介于 [ l , r ] [l,r] [l,r] 之间。如果 a a a 的值介于 [ l , r ] [l,r] [l,r] 之间,那么顾客可以直接选择买 a a a 罐猫粮,这样顾客最终只会正好买 a a a 罐猫粮,而不会多买。
x m o d    a ≥ a 2 x\mod a≥\frac{a}{2} xmoda2a,要想这个等式成立,就要使左边大右边小,而左边大的实现方法就是让 a > x a>x a>x,这样取余永远为 x x x,而右边小的实现方法就是要让 a a a尽量小。 x x x 最大为 r r r,定 a a a r + 1 r+1 r+1,那么即可进行判断了。

Code:
int main()
{
    int t;
    sd(t);
    while (t--)
    {
        int l, r;
        sdd(l, r);
        if (l % (r + 1) >= (r + 1) * 1.0 / 2)
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}

B. Reverse Binary Strings

题意;

给你一个长度为 n n n 的字符串 s s s,其中 n n n 是偶数,并且 s s s 是二进制串,即只由 0 0 0 1 1 1组成。
s s s n 2 \frac{n}{2} 2n 0 0 0 n 2 \frac{n}{2} 2n 1 1 1 n n n是偶数)。
在一次操作中,你可以翻转 s s s 的任意子串,一个字符串的子串指的是该字符串的一段连续的字符串。
你需要执行多少次这样的操作,使得字符串中的 0 0 0 1 1 1是交替出现的。比如: 01010101 … 01010101… 01010101 10101010 … 10101010… 10101010

如果有连续的数字,就需要翻转子字符串,而且每次翻转可以消除一对连续的 00 00 00 或者 11 11 11
例如:

10011001 10011001 10011001

第一次翻转:

10101001 10101001 10101001

第二次翻转:

10101010 10101010 10101010

当有很长的连续字符时:

11000011 11000011 11000011

第一次翻转:

10100011 10100011 10100011

第二次翻转:

10101100 10101100 10101100

第三次翻转:

10101010 10101010 10101010

所以只要统计连续的 0 0 0 和连续 1 1 1 的对数去大值即可。

Code:
const int N = 2e5 + 10;
int n, m;
char s[N];
 
int main()
{
    int t;
    sd(t);
    while (t--)
    {
        sd(n);
        ss(s + 1);
        int cnt0 = 0, cnt1 = 0;
        rep(i, 2, n)
        {
            if (s[i] == s[i - 1])
            {
                if (s[i] == '0')
                    cnt0++;
                else
                    cnt1++;
            }
        }
        pd(max(cnt0, cnt1));
    }
    return 0;
}

C. Chef Monocarp

题意;

n n n 个菜同时放进烤箱,第 i i i 个菜的最佳烹饪时间是 t i t_i ti,如果第 i i i 个菜在 T T T 时间被端出,那么对它的不满意值就是 ∣ T − t i ∣ |T−t_i| Tti,且在每一个时刻只能端出一个菜,问不满意值和的最小值。

最佳烹饪时间值小的肯定要先取出,先将这 n n n 个菜品按照最佳烹饪时间值排序。

他们最好的时间 t i < = n t_i<=n ti<=n。从 n n n 开始拿出盘子,最多用 2 ∗ n 2*n 2n 的时间可以拿完。

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 j − 1 j-1 j1个物品都取出时,第 j j j 个物品在 i i i 时刻取出需要花费的最小总时间。

可以求出状态转移方程:

d p [ i ] [ j ] = m i n { d p [ i ] [ j ] , d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] 、 、 、 d p [ i − 1 ] [ j − 1 ] } + a b s ( T − t i ) dp[i][j]=min\{dp[i][j],dp[i-1][1],dp[i-1][2]、、、dp[i-1][j-1]\}+abs(T-t_i) dp[i][j]=min{dp[i][j],dp[i1][1],dp[i1][2]dp[i1][j1]}+abs(Tti)

Code:
const int N = 500;
int n, m;
int a[N], dp[N][N];

int main()
{
    int t;
    sd(t);
    while (t--)
    {
        sd(n);
        rep(i, 1, n)
            sd(a[i]);
        sort(a + 1, a + 1 + n);
        mem(dp, inf);
        dp[0][0] = 0;
        rep(i, 1, 2 * n)
        {
            rep(j, 0, n)
            {
                dp[i][j] = min(dp[i][j], dp[i - 1][j]);
                if (j)
                    dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + abs(a[j] - i));
            }
        }
        pd(dp[2 * n][n]);
    }
    return 0;
}

D. Minimal Height Tree

题意;

n n n个结点的 b f s bfs bfs 的遍历顺序,每个结点的子节点是按照升序从左到右排列的,求最少的层数。

开始是一个根,如果有多少递增的就说明第二层有多少根,变小说明换新的节点添加。

Code:
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stack>
#include <queue>
#include <unordered_map>
using namespace std;
#define sd(n) scanf("%d", &n)
#define sdd(n, m) scanf("%d%d", &n, &m)
#define sddd(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n, m) printf("%d %d\n", n, m)
#define pddd(n, m, z) printf("%d %d %d\n", n, m, z)
#define pld(n) printf("%lld\n", n)
#define pldd(n, m) printf("%lld %lld\n", n, m)
#define plddd(n, m, z) printf("%lld %lld %lld\n", n, m, z)
#define sld(n) scanf("%lld", &n)
#define sldd(n, m) scanf("%lld%lld", &n, &m)
#define slddd(n, m, k) scanf("%lld%lld%lld", &n, &m, &k)
#define sf(n) scanf("%lf", &n)
#define sc(n) scanf("%c", &n)
#define sff(n, m) scanf("%lf%lf", &n, &m)
#define sfff(n, m, k) scanf("%lf%lf%lf", &n, &m, &k)
#define ss(str) scanf("%s", str)
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = a; i >= n; i--)
#define mem(a, n) memset(a, n, sizeof(a))
#define debug(x) flagt << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define ce i == n ? '\n' : ' '
#define mod(x) ((x) % MOD)
#define gcd(a, b) __gcd(a, b)
#define lowbit(x) (x & -x)
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
inline int read()
{
    int ret = 0, sgn = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            sgn = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        ret = ret * 10 + ch - '0';
        ch = getchar();
    }
    return ret * sgn;
}
inline void write(int x) //ê?3?ía1ò
{
    if (x >= 10)
        write(x / 10);
    putchar(x % 10 + '0');
}

ll GCD(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}

ll lcm(ll a, ll b)
{
    return a * b / GCD(a, b);
}

///快速幂m^k%mod
ll qpow(ll x, ll n, ll mod)
{
    ll num = 1;
    while (n)
    {
        if (n & 1)
            num = (num * x) % mod;
        x = x * x % mod, n >>= 1;
    }
    return num;
}

int resow(int x, int n)
{
    int num = 1;
    while (n)
    {
        if (n & 1)
            num *= x;
        x = x * x;
        n >>= 1;
    }
    return num;
}

const int N = 2e5 + 50;
int n, m;
int a[N];
int ans, maxn, sum, rootsum, len;
bool flag;
int main()
{
    int t;
    sd(t);
    while (t--)
    {
        sd(n);
        rep(i, 1, n)
            sd(a[i]);
        rootsum = 1;
        sum = 0;
        flag = 0;
        ans = 0;
        rep(i, 2, n)
        {
            int j = i + 1;
            maxn = a[i];
            while (a[j] > maxn && j <= n)
            {
                maxn = max(maxn, a[j]);
                j++;
            }
            len = j - i;;//找到a[i]为首项最长的上升子序列
            i = j - 1;
            rootsum--;//可以作为根节点的节点数-1;
            sum += len;//当前层数的节点数
            flag = 1;//当前开始了这一层但是没有添加完,最后把这一层给加上
            if (!rootsum)//没有根节点开始下一层
            {
                rootsum = sum;
                sum = 0;
                flag = 0;
                ans++;
            }
        }
        if (flag)
            ans++;
        pd(ans);
    }
    return 0;
}

E. Make It Increasing

题意;

有一个数组 a a a,数组某些位置的数不可操作,其余位置的数可以进行操作,将其赋为任意值。求最少的操作次数,使数组 a a a 为升序序列,或者输出无解。

若两个相邻的不可动的位置的值的差小于他们之间的距离,则无解。即 a p o s 2 − a p o s 1 < p o s 2 − p o s 1 a_{pos2}-a_{pos1} < pos2-pos1 apos2apos1<pos2pos1 时无解。

m = 0 m = 0 m=0,也就是没有数字被锁定的情况,求解最长不下降子序列,然后答案就是 n - ans 了。

按照不能修改的位置将数组分割为若干段,我们可以对于每一段单独求解最长不下降子序列,然后计算答案。但是相邻两个被锁定的位置,会限制这个最长不下降子序列的首尾。

Code:
const int N = 5e5 + 50;
int n, m;
int a[N], b[N], c[N], f[N];
int ans, pos, top;

int main()
{
    int t;
    sdd(n, m);
    rep(i, 1, n)
    {
        sd(a[i]);
        a[i] -= i;
    }
    rep(i, 1, m) sd(b[i]);
    a[0] = -inf;
    a[n + 1] = inf;
    b[0] = 0;
    b[m + 1] = n + 1;
    int ans = 0;
    rep(i, 0, m)
    {
        int l = b[i], r = b[i + 1];
        if (a[l] > a[r])
        {
            puts("-1");
            return 0;
        }
        int top;
        f[top = 1] = a[l];
        rep(i, l + 1, r)
        {
            if (a[i] >= f[top])
            {
                f[++top] = a[i];
                if (i == r)
                    ans += (r - l + 1) - top;
            }
            else
            {
                int p = upper_bound(f + 1, f + top + 1, a[i]) - f;
                if (p != 1)
                    f[p] = a[i];
                if (i == r)
                    ans += (r - l + 1) - p;
            }
        }
    }
    pd(ans);
    return 0;
}
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值