Codeforces Round #706 (Div. 2) ABC

Codeforces Round #706 (Div. 2) ABC

A - Split it!

题意

找到 k + 1 k + 1 k+1 个字符串,使得 a 1 + a 2 + ⋯ + a k + a k + 1 + R e v e r s e ( a k ) + ⋯ + R e v e r s e ( a 2 ) + R e v e r s e ( a 1 ) a_1 + a_2 + \dots + a_k + a_{k + 1} + Reverse(a_k) + \dots + Reverse(a_2) + Reverse(a_1) a1+a2++ak+ak+1+Reverse(ak)++Reverse(a2)+Reverse(a1) 等于长度为 n n n 的字符串 s s s

思路

k = 0 k = 0 k=0 肯定可以,其他情况判断是否有 k k k 个字符满足 s i = s n − i   ( i ∈ [ 1 , k ] ) s_i = s_{n - i} \ (i \in [1, k]) si=sni (i[1,k]) ,并且 k   ! = n − k k \ != n - k k !=nk (即除了外面回文这一圈,中间还有剩下的)

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e4 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;

int n, k;
string a;

bool ok()
{
    if(k == 0)
        return 1;
    for(int i = 0, j = n - 1; i < j - 1; i++, j--)
    {
        if(a[i] != a[j])
            return 0;
        if(i >= k - 1)
            return 1;
    }
    return 0;
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n >> k;
        cin >> a;
        if(ok())
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}

B - Max and Mex

题意

给定集合 s s s ,每次取其中最大值 x x x 和最小的未出现过的数 y y y ,将 ⌈ a + b 2 ⌉ \lceil \frac{a + b}{2}\rceil 2a+b 放入集合。问 操作 k k k 次后集合内不重复元素的个数是多少?

思路

首先k=0肯定可以,其他的三种情况,第一种 ⌈ a + b 2 ⌉   >   n \lceil \frac{a + b}{2}\rceil \ > \ n 2a+b  n ,这种情况 k k k 次后增加 k k k 个;其他情况再分为两种,第一种 ⌈ a + b 2 ⌉ \lceil \frac{a + b}{2}\rceil 2a+b 在原集合中不存在,个数为原集合+1;第二种存在,个数就是原集合个数。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e5 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;

ll n, k;
map<ll, ll> mp;
set<ll> st;

int solve(int& l, int maxx)
{
    int mexx;
    for(mexx = l + 1; mexx <= maxx; mexx++)
    {
        if(!mp[mexx])
            break;
    }
    l = mexx;
    int ans = (mexx + maxx + 1) / 2;
    return ans;
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n >> k;
        mp.clear();
        st.clear();
        int maxx = -1;
        for(int i = 0, x; i < n; i++)
        {
            cin >> x;
            st.insert(x);
            mp[x] = 1;
            maxx = max(maxx, x);
        }
        if(k == 0)
        {
            cout << st.size() << endl;
            continue;
        }
        int mexx = -1;
        int nxt = solve(mexx, maxx);
        if(mexx > maxx)
        {
            cout << st.size() + k << endl;
            continue;
        }
        int ans = st.size();
        if(st.find(nxt) == st.end())
        {
            ans++;
        }
        cout << ans << endl;
    }
    return 0;
}

C - Diamond Miner

题意

n n n 个矿工都在 y y y 轴上, n n n 个钻石都在 x x x 轴上,每个人挖一个矿,如何使所有人和自己挖的矿的距离之和最小?

思路

把钻石和人都按照和x轴距离排序,然后最近的人挖最近的矿就行。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e5 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;

int n;
double x, y;
vector<double> goal;
vector<double> miner;

double dis(double x, double y)
{
    return sqrt(x * x + y * y);
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        miner.clear();
        goal.clear();
        for(int i = 0, a, b; i < 2 * n; i++)
        {
            cin >> a >> b;
            if(a == 0)
            {
                b = abs(b);
                miner.pb((double)b);
            }
            else
            {
                a = abs(a);
                goal.pb((double)a);
            }
        }
        sort(miner.begin(), miner.end());
        sort(goal.begin(), goal.end());
        double ans = 0;
        for(int i = 0; i < n; i++)
        {
            ans += dis(miner[i], goal[i]);
        }
        printf("%.10f\n", ans);
    }
    return 0;
}

总结

第一次遇到这么顺利的vp,都是一遍过的,就是很遗憾D题罚坐了一个小时,,,不过这个过题人数确实少,明天补吧

多多包涵,共同进步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值