Codeforces Round #706 (Div. 2) A-D题解

写在前边

链接:Codeforces Round #706 (Div. 2)
A,B,C,D,这场有点简单,不过由于A写炸了后边题连看都没看就溜了,就从上大分变成了掉大分

A. Split it!

链接:A题链接

题目大意:

给定一个字符串s,和一个数字k,那么ais的一个子串,Rai代表ai的逆序,问是否满足:

s=a1+a2+...+ak+ak+1+R(ak)+R(ak1)+...+R(a1)

思路

首先要知道,有一个单独的ak+1部分,那么这部分,根本无所谓,但是对于它的两侧必然要是回文的,一开始就拽着回文串不放了,思维定势,以为全串必然要是回文才行,所以写炸了,所以只需要判断s[1,k]是否等于s[nk+1,n](下标从1开始)即可,还要注意的是如果这个串的长度为偶数,那么k必然不能等于s.size()2

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
#define pub push_back
#define pob pop_back

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

const int Mod = 10000007;

LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}

void solve() {
    string s;
    int n, k;
    cin >> n >> k;
    cin >> s;
    if (k == 0) {
        puts("YES");
        return;
    }

    //这题并不一定要求中间是回文的
    if (s.size() % 2 == 0 && k == s.size() / 2) {
        puts("NO");
        return;
    }
    bool flag = true;
    for (int i = 0; i < k; i++) {
        if (s[i] != s[s.size() - 1 - i]) {
            flag = false;
            break;
        }
    }
    puts(flag ? "YES" : "NO");
}

int main()
{
    //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    scanf("%d", &t); 
    while (t--) {
        solve();
    }
    return 0;
}

B. Max and Mex

链接:B题链接

题目大意:

给定一个序列s,我们可以进行k次操作,每次操作是添加一个a+b2,a=mex(s), b=max(s),max就是序列中最大的数字,mex表示序列中最小不存在的非负整数,例如在序列0124中,那么mex=3,问k次插入后,S中不同数字的个数有多少。

思路

先找到第一个mex,如果mex<=max(S),可以发现,插入一个a+b2,永远不会出现这个数,因此,mex就永远不会变化,与此同时插入的值也永远不会大于max,所以mex与max不变,那么序列中不同数的个数最多就加1,用一个set维护就好。
如果mex==max(S),即假设序列为0,1,2,3,那么第一个mex就是4,所以a+b2算出来就是mex,就插入一个新值,所以这种情况下,有多少个k,就插入多少个新值。

注意:取最大值的时候要看要注意数组并不一定是严格有序的啊!!

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
#include <set>

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
#define pub push_back
#define pob pop_back

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;


const int Mod = 10000007;

LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}

const int N = 1e5 + 10;
int a[N];

//题目没说给有序数组大哥
void solve() {
    int n, k;
    scanf("%d%d", &n, &k);
    multiset<int> st2; //记录没有的数字 最小的数字
    set<int> st3;

    for (int i = 0; i < n; i++) scanf("%d", &a[i]);       
    
    sort(a, a + n);
    for (int i = 0; i < n; i++) {
        st3.insert(a[i]);
        st2.insert(a[i]);  
    }

    if (k == 0) {
        cout << st3.size() << endl;
        return;
    }

    int m = 0;
    for (auto &it : st2) {
        if (m != it) {
            break;
        }
        m++;
    }

    if (m > a[n - 1]) cout << n + k << endl;
    else {
        st3.insert((m + a[n - 1] + 1) / 2);
        cout << st3.size() << endl;
    }
}

int main()
{
    //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    scanf("%d", &t); 
    while (t--) {
        solve();
    }

    return 0;
}

C. Diamond Miner

链接:C题链接

题目大意:

不说了,太简单了。

思路

排序,贪心求值就好了

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
#include <cmath>

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
#define pub push_back
#define pob pop_back

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

const int Mod = 10000007;

const int N = 1e5 + 10;

void solve() {
    int n;
    scanf("%d", &n);
    vector<int> a, b;
    for (int i = 0; i < n * 2; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (x == 0) b.push_back(abs(y));
        if (y == 0) a.push_back(abs(x));
    }
    
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    
    double res = 0.0;
    for (int i = 0; i < n; i++) {
        res += sqrt((LL) a[i] * a[i] + (LL) b[i] * b[i]); //千万不要忘记long long
    }
    printf("%.15lf\n", res);
}

int main()
{
    //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    scanf("%d", &t); 
    while (t--) {
        solve();
    }

    return 0;
}

D. Let's Go Hiking

链接:D题链接

题目大意:

给题目大意转化一下就是,小A只能走一条单调递减序列,小B只能走一条单调递减序列,直到到某个人走的时候这个人无路可走了那么他就输了。题目中为小A先选一个起点,然后小B后选一个起点,接下来,小A先做决策,再B做决策,两者选择永远最优,问最后小A。

思路

是一道博弈论的题目,两个人都是在单调的路上走,并且对于B来说,肯定要想办法让A输,A肯定想找一条最长的路走,所以有下面几种情况:
如果两个以上的单调段,那么先手必然输,因为:

  1. 如果是全是一个方向的单调段,那么小A无论如何都会被小B堵截。
  2. 如果对于山峰段,即一个点左右分别为单调递增单调递减,有多个,那么B后手总能选到一个地方赢得比赛(画几个例子试试)。
  3. 如果对于山谷段,及一个点左右分别为单调递减单调递增,有多个,那么B后手也同样总能选到一个地方赢得比赛(画几个例子试试)。

如果就只有一个单调段,那么更不用说了,B只需要放在A旁边堵A即可,赢得比赛。

所以如果想要先手赢,那么必然是只要一个山峰段,同时山峰段还要左右恰好对称才可以,如果不对称那B也可以找一个地方拦截A,或者走的路比更长,如果对称情况下,A必然选择连接点,而这时小B只能选两端点,这时如果A躲避B走另一边,那么它无论如何都输,因此他只能跟B对着走,而这时如果maxl,那么它依然输,所以只有maxl情况下同时是对称的山峰段才赢,其余情况均输。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
#define pub push_back
#define pob pop_back

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;

const int Mod = 1000000007;

LL gcd(LL a, LL b) {
    return b ? gcd(b, a % b) : a;
}

const int N = 1E5 + 10;
int n, p[N];
int pre[N], suff[N];

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &p[i]);

    for (int i = 1; i <= n; i++) {
        if (p[i] > p[i - 1]) pre[i] = pre[i - 1] + 1;
        else pre[i] = 1;
    }
    for (int i = n; i >= 1; i--) {
        if (p[i] > p[i + 1]) suff[i] = suff[i + 1] + 1;
        else suff[i] = 1;
    }

    /* for (int i = 1; i <= n; i++) cout << pre[i] << " ";
    cout << endl;
    for (int i = 1; i <= n; i++) cout << suff[i] << " ";
    cout << endl; */

    int maxl = 0;
    for (int i = 1; i <= n; i++) maxl = max({maxl, pre[i], suff[i]});

    int cnt1 = 0, cnt2 = 0, idx1 = 0, idx2 = 0;
    for (int i = 1; i <= n; i++) {
        if (pre[i] == maxl) {
            cnt1++;
            idx1 = i;
        }
        if (suff[i] == maxl) {
            cnt2++;
            idx2 = i;
        }
    }

    if (cnt1 + cnt2 != 2) {
        puts("0");
        return;
    } else if (cnt1 + cnt2 == 2 && idx1 == idx2) {   
        puts(maxl % 2 == 0 ? "0" : "1");
    } else puts("0");
}

int main()
{
    //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    solve();
    return 0;
}
posted @   Xxaj5  阅读(78)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示