Educational Codeforces Round 39 (Rated for Div. 2)(A-D)(水题 + 模拟 + 贪心模拟 + DP)

昨天用cf的virtual contest开了一场,做的不是特别理想。半个小时A了三题后就一直划水,今天补了D题。

A. Partition

You are given a sequence a consisting of n integers. You may partition this sequence into two sequences b and c in such a way that every element belongs exactly to one of these sequences.

Let B be the sum of elements belonging to b, and C be the sum of elements belonging to c (if some of these sequences is empty, then its sum is 0). What is the maximum possible value of B - C?

Input

The first line contains one integer n (1 ≤ n ≤ 100) — the number of elements in a.

The second line contains n integers a1a2, ..., an ( - 100 ≤ ai ≤ 100) — the elements of sequence a.

Output

Print the maximum possible value of B - C, where B is the sum of elements of sequence b, and C is the sum of elements of sequence c.

Examples
input
Copy
3
1 -2 0
output
3

A题:给出含有n个数的数列,问能能否分出两个子序列,使两个子序列中元素的和,相减后最大,最大是多少?子序列可以为空

输入输出的水题,遍历整个数组,正数加,负数减。最后得到的一定最大。

int main() {
    int n, sum = 0, num;
    scanf("%d", &n);
    for(int i=0;i<n;i++){
        scanf("%d",&num);
        sum += fabs(num);
    }
    printf("%d\n",sum);

    return 0;
}

B. Weird Subtraction Process

You have two variables a and b. Consider the following sequence of actions performed with these variables:

  1. If a = 0 or b = 0, end the process. Otherwise, go to step 2;
  2. If a ≥ 2·b, then set the value of a to a - 2·b, and repeat step 1. Otherwise, go to step 3;
  3. If b ≥ 2·a, then set the value of b to b - 2·a, and repeat step 1. Otherwise, end the process.

Initially the values of a and b are positive integers, and so the process will be finite.

You have to determine the values of a and b after the process ends.

Input

The only line of the input contains two integers n and m (1 ≤ n, m ≤ 1018). n is the initial value of variable a, and m is the initial value of variable b.

Output

Print two integers — the values of a and b after the end of the process.

Examples
input
Copy
12 5
output
0 1

B题:给出a,b两个数。并给出操作,如果一个数是另一个数的两倍及以上,就用大数减去小数的两倍。知道一个是0或者不构成两倍关系。一开始的想法是既然是两倍两倍的,那是不是就是每次二分,那是不是就是logn级别的,那1e18的数据量也能过。就又是直接莽了一发模拟。结果TLE。然后想一想因为小数不确定大小,每次并不一定是二分,eg. 1e18  1这两个数每次减2肯定超时。然后就用除法操作优化了一下就过了

namespace Solver {
    LL a, b;
    void solve(){
        cin>>a>>b;

        while(a && b)
        {
            if(a/b >= 2)
                a -= (a/b)/2*2*b;
            else if(b/a >= 2)
                b -= (b/a)/2*2*a;
            else break;
        }
        cout<<a<<" "<<b<<endl;
    }
};

C. String Transformation

You are given a string s consisting of |s| small english letters.

In one move you can replace any character of this string to the next character in alphabetical order (a will be replaced with bs will be replaced with t, etc.). You cannot replace letter z with any other letter.

Your target is to make some number of moves (not necessary minimal) to get string abcdefghijklmnopqrstuvwxyz (english alphabet) as a subsequence. Subsequence of the string is the string that is obtained by deleting characters at some positions. You need to print the string that will be obtained from the given string and will be contain english alphabet as a subsequence or say that it is impossible.

Input

The only one line of the input consisting of the string s consisting of |s| (1 ≤ |s| ≤ 105) small english letters.

Output

If you can get a string that can be obtained from the given string and will contain english alphabet as a subsequence, print it. Otherwise print «-1» (without quotes).

Examples
input
Copy
aacceeggiikkmmooqqssuuwwyy
output
abcdefghijklmnopqrstuvwxyz

C题:给出一个只含有小写字母的串,每个字母可以通过一次操作变成字典序中的下一子母,z不能变。问能否将原串通过这种操作变成一个,含有‘a-z’做子序列的串。

因为我们顺序需要 a-z 而字典序靠后的不能变成前面的字母。那就将我们需要的字母记成p,p从a开始,发现ascall码小于等于p的就改变该字母为p,p++。当z也找到时直接跳出即可。

而这道题当时用google翻译的时候,把105看成了105,数组开小了wa了一发...

namespace Solver {
    char a[100010];
    void solve(){
        cin>>a;
        int lena = strlen(a);
        char p = 'a';
        for(int i=0; i<lena; i++)
        {
            if(p == 'z'+1 ) break;
            if(a[i] <= p){
                a[i] = p;
                p++;
            }
        }
        if(p == 'z'+1) cout<<a<<endl;
        else cout<<-1<<endl;
    }
};


D. Timetable

Ivan is a student at Berland State University (BSU). There are n days in Berland week, and each of these days Ivan might have some classes at the university.

There are m working hours during each Berland day, and each lesson at the university lasts exactly one hour. If at some day Ivan's first lesson is during i-th hour, and last lesson is during j-th hour, then he spends j - i + 1 hours in the university during this day. If there are no lessons during some day, then Ivan stays at home and therefore spends 0 hours in the university.

Ivan doesn't like to spend a lot of time in the university, so he has decided to skip some lessons. He cannot skip more than k lessons during the week. After deciding which lessons he should skip and which he should attend, every day Ivan will enter the university right before the start of the first lesson he does not skip, and leave it after the end of the last lesson he decides to attend. If Ivan skips all lessons during some day, he doesn't go to the university that day at all.

Given nmk and Ivan's timetable, can you determine the minimum number of hours he has to spend in the university during one week, if he cannot skip more than k lessons?

Input

The first line contains three integers nm and k (1 ≤ n, m ≤ 5000 ≤ k ≤ 500) — the number of days in the Berland week, the number of working hours during each day, and the number of lessons Ivan can skip, respectively.

Then n lines follow, i-th line containing a binary string of m characters. If j-th character in i-th line is 1, then Ivan has a lesson on i-th day during j-th hour (if it is 0, there is no such lesson).

Output

Print the minimum number of hours Ivan has to spend in the university during the week if he skips not more than k lessons.

Examples
input
Copy
2 5 1
01001
10110
output
5

D题:一周有n天,每天有m个小时,用01串表示该小时有没有课。每天的第一节课前到校,最后一节课结束后离开。一周可以翘k节课。问一周至少要在学校呆几天。

昨天做这道题的想法是,翘课肯定不会从一天中间的某节课翘课,而是从第一节或者最后一节开始。所以我们一个vector记录每天翘每节课的影响,然后遍历头尾贪心求解。可是这样做的问题是,当翘课数变化时,翘课的方式不具有继承关系。例如110001101,翘两节课肯定是从后往前两节最优,而翘三节课又变成了前三节最优。然后当时就蒙了不知道要怎么做。

今天查了题解才明白过来,这种子结构最优情况的题,第一反应应该就是dp了。我们记dp[i][j]为前i天,翘j节课,呆在学校的最少时间。并且预处理一个数组mm[i][j]表示第i天,翘j节课,呆在学校的最短时间。则,dp[i][j] = min(dp[i-1][j-len] + mm[i][len]); dp可解。

namespace Solver {
    int n, m, k;
    int cnt[maxn];
    void solve()
    {
        memset(mm, INF, sizeof mm);
        memset(dp, INF, sizeof dp);
        scanf("%d%d%d", &n, &m, &k);
        for(int i=0; i<n; i++){
            scanf("%s", day);
            for(int j=0; j<m; j++)
                if(day[j] == '1') v[i].push_back(j);
        }

        for(int i=0; i<n; i++)
        {
            if(!v[i].size()){
                mm[i][0] = 0;
                continue;
            }

            mm[i][v[i].size()] = 0;
            mm[i][0] = v[i][v[i].size()-1] - v[i][0] + 1;
            for(int l = 0; l < v[i].size(); l++)
                for(int r = l; r < v[i].size(); r++)
                {
                    int att_class = r-l+1;   ///参加课程节数
                    int att_time = v[i][r] - v[i][l] + 1;   ///参加课程时间
                    int kip_class = v[i].size() - att_class; ///跳过课程数

                    umin(mm[i][kip_class], att_time);
                }
        }

        for(int i=0; i<=v[0].size(); i++)
            dp[0][i] = mm[0][i];

        for(int i=1; i<n; i++)
        {
            for(int j=0; j<=k; j++)
            {
                for(int len = 0; len<=j; len++)

                    umin(dp[i][j], dp[i-1][j-len] + mm[i][len]);
            }
        }

        int minn = INF;
        for(int i=0; i<=k; i++)
            umin(minn, dp[n-1][i]);

        printf("%d\n", minn);

    }
};

最后选择了一个for循环来取minn的值,是因为如果k比总课程大的话,dp[n-1][k] 所对应的为恰好翘k节课的时间会出问题。然后在预处理mm的时候使用了枚举连续区间[l,r]作为上课区间,而不是用头尾翘课的方式。当时脑子里有些懵所以用了特殊的变量名并打了注释。还是很好理清思路的。


这场cf出了三个简单题,栽了一道dp。可是简单题并没有保证手速和正确率,B C两题各WA了一发,如果是真的在打场的话应该就凉了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值