Codeforces Round #719 (Div. 3) Editorial

传送门

A. Do Not Be Distracted!

题目描述:

Polycarp has 2626 tasks. Each task is designated by a capital letter of the Latin alphabet.

The teacher asked Polycarp to solve tasks in the following way: if Polycarp began to solve some task, then he must solve it to the end, without being distracted by another task. After switching to another task, Polycarp cannot return to the previous task.

Polycarp can only solve one task during the day. Every day he wrote down what task he solved. Now the teacher wants to know if Polycarp followed his advice.

For example, if Polycarp solved tasks in the following order: "DDBBCCCBBEZ", then the teacher will see that on the third day Polycarp began to solve the task 'B', then on the fifth day he got distracted and began to solve the task 'C', on the eighth day Polycarp returned to the task 'B'. Other examples of when the teacher is suspicious: "BAB", "AABBCCDDEEBZZ" and "AAAAZAAAAA".

If Polycarp solved the tasks as follows: "FFGZZZY", then the teacher cannot have any suspicions. Please note that Polycarp is not obligated to solve all tasks. Other examples of when the teacher doesn't have any suspicious: "BA", "AFFFCC" and "YYYYY".

Help Polycarp find out if his teacher might be suspicious.

题意:

给你一堆任务,同一种任务只能在一段时间内解决,超过这段时间就无法解决这个问题。如果能解决全部问题就输出YES,否则就输出NO

思路:

遍历这个字符串,对于一段时间的任务,如果没有被标记过,就标记一下,如果被标记过了,说明在这段时间前面出现了同样的任务,就跳出循环输出NO即可

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}

int n, t;
string s;
int tr[MAX];

int main(){
    cin>>t;
    while (t--) {
        bool k = 0;
        mem(tr, 0);
        cin>>n>>s;
        for(int i = 0; i < s.size(); ++i){
            if(tr[s[i] - 'A' + 1]){
                k = 1;
                cout<<"NO\n";
                break;
            }
            else tr[s[i] - 'A' + 1] = 1;
            while (s[i] == s[i + 1]) {
                ++i;
            }
        }
        if(!k)cout<<"YES\n";
    }
    return 0;
}

B. Ordinary Numbers

题目描述:

Let's call a positive integer nn ordinary if in the decimal notation all its digits are the same. For example, 1,2 and 99 are ordinary numbers, but 719 and 2021 are not ordinary numbers.

For a given number nn, find the number of ordinary numbers among the numbers from 1 to n.

题意:

一个数n他的所有位的数字都相同就是ordinary数字,问你从1到n之间有多少个ordinary数字

思路:

看着很水的一个题,我却wa了两次(╥﹏╥)

对于一个数位为k的数字n,它从1开始每多一位数,最多能出现9个ordinary数,所以就用k-1乘以9,再加上数位为k且小于等于n的ordinary数的个数即可

对于数位为k且小于等于n的ordinary数怎么求就是一个坑点,一开始我是取每一位的最小值,后来wa了两发自闭以后才发现不对,因为对于2312它就可以取2222,所以我取出最高位为r,让ans+=(r - 1),再判断原来的数n与 k位r的十进制数(也就是每一位都是r的k位十进制数)进行比较,如果大于则ans++……

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}

int n, t;

int main(){
    cin>>t;
    while (t--) {
        cin>>n;
        int p = n;
        int num = 0, minx = 1e9, x = 0;
        int ans = 0;
        while (n) {
            x = n % 10;
            ++num;
            minx = min(minx,n % 10);
            n /= 10;
        }
        int k = 0;
        ans += x - 1;
        for(int i = 1; i <= num; ++i){
            k *= 10;
            k += x;
        }
//        cout<<k<<endl;
        if(p >= k)++ans;
        ans += (num - 1) * 9;
        cout<<ans<<endl;
    }
    return 0;
}

C. Not Adjacent Matrix

题目描述:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qKlU6RBG-1620390905035)(/Users/chelsea/Library/Application Support/typora-user-images/image-20210507193441572.png)]

题意:

构造一个n * n的矩阵,将1-n * n的数全塞进去,其中大小相差为1的数不可以位于相邻的上下左右位置,如果不能构造出来就输出-1

思路:

只有n=2时无法构造成功

对于其他的,只需要先输出所有奇数,再输出所有偶数即可

再就是注意注意细节

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}

int n, t;

int main(){
    cin>>t;
    while (t--) {
        cin>>n;
        if(n == 2)cout<<-1<<endl;
        else if(n % 2 == 1){//奇数
            int x = 1;
            for(int i = 1; i <= n / 2; ++i){
                for(int j = 1; j <= n; ++j){
                    cout<<x<<' ';
                    x += 2;
                }
                cout<<endl;
            }
            for(int i = 1; i <= n / 2 + 1; ++i){
                cout<<x<<' ';
                x += 2;
            }
            x = 2;
            for(int i = 1; i <= n / 2; ++i){
                cout<<x<<' ';
                x += 2;
            }
            cout<<endl;
            for(int i = 1; i <= n / 2; ++i){
                for(int j = 1; j <= n; ++j){
                    cout<<x<<' ';
                    x += 2;
                }
                cout<<endl;
            }
        }
        else {//偶数
            int x = 1;
            for(int i = 1; i <= n / 2; ++i){
                for(int j = 1; j <= n; ++j){
                    cout<<x<<' ';
                    x += 2;
                }
                cout<<endl;
            }
            x = 2;
            for(int i = 1; i <= n / 2; ++i){
                for(int j = 1; j <= n; ++j){
                    cout<<x<<' ';
                    x += 2;
                }
                cout<<endl;
            }
        }
    }
    return 0;
}

D. Same Differences

题目描述:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gQRWoBDO-1620390905036)(/Users/chelsea/Library/Application Support/typora-user-images/image-20210507194008107.png)]

题意:

给你一个数组a, 问你有多少对(i,j)满足\(i < j,a[j] - a[i] = j - i\)

思路:

看到这个式子,不难想到要对其移向合并(我就没想到,艹

a[j] - j = a[i] - i

然后就可以用map乱搞,不过别忘了给map初始化

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}

int t;
int n;
int tr[MAX];
map<int, int>mp;

int main(){
    cin>>t;
    while (t--) {
        mp.clear();
        ll ans = 0;
        n = IntRead();
        for(int i = 1; i <= n; ++i){
            tr[i] = IntRead();
            ans +=  mp[tr[i] - i];
            ++mp[tr[i] - i];
        }
        cout<<ans<<endl;
    }
    return 0;
}

E. Arranging The Sheep

题目描述:

You are playing the game "Arranging The Sheep". The goal of this game is to make the sheep line up. The level in the game is described by a string of length nn, consisting of the characters '.' (empty space) and '*' (sheep). In one move, you can move any sheep one square to the left or one square to the right, if the corresponding square exists and is empty. The game ends as soon as the sheep are lined up, that is, there should be no empty cells between any sheep.

For example, if n=6n=6 and the level is described by the string "**.*..", then the following game scenario is possible:

  • the sheep at the 44 position moves to the right, the state of the level: "**..*.";
  • the sheep at the 22 position moves to the right, the state of the level: "..*.";
  • the sheep at the 11 position moves to the right, the state of the level: ".**.*.";
  • the sheep at the 33 position moves to the right, the state of the level: ".*.**.";
  • the sheep at the 22 position moves to the right, the state of the level: "..***.";
  • the sheep are lined up and the game ends.

For a given level, determine the minimum number of moves you need to make to complete the level.

题意:

给你一个字符串,有羊🐑 '*' 和 空地 '.' ,问你将所有羊移到一起(也就是任意的相邻的羊之间没有空地)最小的移动次数是多少

思路:

绝对值不等式的贪心

先来看一个例题:

104. 货仓选址

在一条数轴上有 NN 家商店,它们的坐标分别为 A1∼AN。

现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。

为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小

思路:

考虑只有两家店a,b 时,货仓的位置x到两家商店的距离 l 就满足绝对值不等式 \(l = |x - a| + |x - b| >= |a - b|\)

则当a ≤ x ≤ b a≤x≤ba≤x≤b时, 不等式取等,此时距离最小. 即货仓要建在两店之间(包括端点)

考虑n家商店, n为奇数时, 建在最中间的商店处最优. n为偶数时, 建在最中间的两点之间最优

注意要排序啊,还有这个题会爆int,所以得开longlong

AC代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using  namespace std;
#define inf 0x3f3f3f3f
#define MAX 200000 + 50
#define endl '\n'
//#define mod 1000000007
//const int mod = 1e9 + 7;
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}

int n, k;
ll ans;
int tr[MAX];

int main(){
    cin>>n;
    for(int i = 1; i <= n; ++i){
        cin>>tr[i];
    }
    sort(tr + 1, tr + 1 + n);
    if(n % 2 == 1){
        k = n / 2 + 1;
        for(int i = 1; i <= n; ++i){
            ans += fabs(tr[i] - tr[k]);
        }
        cout<<ans<<endl;
    }
    else {
        k = n / 2;
        int p = (tr[k] + tr[k + 1]) / 2;
        for(int i = 1; i <= n; ++i){
            ans += fabs(tr[i] - p);
        }
        cout<<ans<<endl;
    }
    return 0;
}

现在再回到CF的E题上来,这题就是一道绝对值不等式的贪心

最优解可以是以某群羊为中心,左右两侧合并起来

注意⚠️这里说的是“可以是”,因为最优解的方法不唯一

所以本题应该先找出来中位数,然后根据羊的个数,去确定最终羊所在的区间是哪里,然后用区间的每个位置 i 去减去羊的位置,要取绝对值,求和即是答案

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}

int t, n, x;
string s;
ll num, ans, l;
vector<int>v;

int main(){
    cin>>t;
    while (t--) {
        cin>>n>>s;
        ans = 0;
        v.clear();
        for(int i = 0; i < n; ++i){
            if(s[i] == '*'){
                v.push_back(i + 1);
            }
        }
        num = v.size();
        if(num % 2 == 1){
            x = v[num / 2];
            l = x - num / 2;
            for(int i = 0; i < num; ++i){
                ans += fabs(v[i] - l);
                ++l;
            }
            cout<<ans<<endl;
        }
        else {
            if(num != 0){
                x = (v[num / 2 - 1] + v[num / 2]) / 2;
                l = x - num / 2 + 1;
                for(int i = 0; i < num; ++i){
                    ans += fabs(v[i] - l);
                    ++l;
                }
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

F1. Guess the K-th Zero (Easy version)

题意:

题干太长了,懒得截图了,直接说题意叭

首先这是个交互题(第一次做交互题(>_<)

有一个数组,里面的元素只有0和1,你可以每次对机器进行形如如下的询问:? a b ,机器会会告诉你a到b直接有几个1,你需要20次询问内找到第k个0的位置并输出! pospos即为第k个0的位置

思路:

显然是一个二分(貌似交互题绝大部分都是二分

写个分治函数,参数是 l, r, k,当l = r 时就输出位置结束程序,否则就是取mid = (l + r) / 2,询问一下l 到 mid 之间有多少个 1(设为ans个),则0 的个数为 r - l + 1 - ans,然后就判断0的个数与k的大小,如果小于k,说明少了,就去二分mid + 1到r,此时要修改参数k的值,差几个k;如果大于k,说明多了,就再去二分l 到 mid。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000007
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline ll LLRead(){ll x(0), t(1);char o (getchar());while (o < '0' || o > '9') {if (o == '-') {t = -1;}o = getchar();}for (; o >= '0' && o <= '9'; o = getchar()) {x = (x << 1) + (x << 3) + (o ^ 48);}return x * t;}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
ll qpow(ll a,ll n){ll ans=1,base=a%mod;while(n){if(n&1)ans=(ans*base)%mod;base=(base*base)%mod;n>>=1;}return ans;}
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }

int n, k, t;

void cal(int l, int r, int k){
    if(l == r){
        cout<<"! "<<l<<endl;
        return;
    }
    int mid = (l + r) / 2;
    cout<<"? "<<l<<' '<<mid<<endl;
    int ans;
    cin>>ans;
    if(mid - l + 1 - ans >= k)cal(l, mid, k);
    else cal(mid + 1, r, k - (mid - l + 1 - ans));
}

int main(){
    cin>>n>>t>>k;
    cal(1, n, k);
    return 0;
}

F题还是一个交互题,不过好像挺难的,G题好像是个带传送门的bfs,但只有245人过了,看样子就不是我这个灰名选手能补的题

posted @ 2021-05-07 20:40  扇与她尽失  阅读(185)  评论(0编辑  收藏  举报
/* 设置签名格式 定制css样式 */ #MySignature { display: none; background-color: #B2E866; border-radius: 10px; box-shadow: 1px 1px 1px #6B6B6B; padding: 10px; line-height: 1.5; text-shadow: 1px 1px 1px #FFF; font-size: 16px; font-family: 'Microsoft Yahei'; }