ABC386题解(ABCDE)

比赛链接:AtCoder Beginner Contest 386

A - Full House 2

思路:就这么几种情况,模拟即可:四个都一样肯定不行;有三个一样的肯定可以;如果是两个一样的就看另外两个是不是也一样否则不行;四个都不一样肯定不行。

#include <bits/stdc++.h>
#define endl '\n'
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, n, a) for (int i = n; i >= a; i--)
#define LL long long
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
using namespace std;
#define MAXN 105

int vs[20];
int a[4];

int main()
{
    IOS;
    rep(i,0,3)
    {
        cin >> a[i];
        vs[a[i]]++;
    }
    bool p2 = 0, p3 = 0, sc = 0;
    rep(i,1,13)
    {
        if(vs[i]==3)
        {
            cout << "Yes";
            return 0;
        }
        else if(vs[i]==2)
        {
            rep(j,i+1,13)
            {
                if(vs[j]==2)
                {
                    cout << "Yes";
                    return 0;
                }
            }
        }
    }
    cout << "No";
    return 0;
}

B - Calculator

思路:1~9的数字串每个数字都必须按一次,而0串按的次数,由于“00”按键的存在,则跟串的长度有关,具体来说,偶数长度按n/2次,奇数长度按(n-1)/2+1次,所以只需要将1~9数字串和0串按的次数分别计算求和即可。

#include <bits/stdc++.h>
#define endl '\n'
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, n, a) for (int i = n; i >= a; i--)
#define LL long long
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
    using namespace std;
#define MAXN 105

string s;
int cnt;

int main()
{
    IOS;
    cin >> s;
    int tmp = 0;
    int tmp2 = 0;
    rep(i, 0, s.size() - 1)
    {
        if (s[i] != '0')
            tmp2++;
        if (s[i] == '0')
            cnt++;
        if ((s[i] != '0' || i == s.size() - 1) && cnt != 0)
        {
            if (cnt % 2 == 0)
                tmp += cnt / 2;
            else
                tmp += (cnt - 1) / 2 + 1;
            cnt = 0;
        }
    }
    cout << tmp2 + tmp;
    return 0;
}

C - Operate 1

思路:有这么几种情况:如果两个串相等,显然编辑距离是0;如果两个串长度之差大于1,显然编辑距离大于1;如果两个串长度之差等于1,那么按位比较字符,如果字符不相等则让较短串的指针等待一次,遍历结束后判断不相等的次数是否为1即可。

#include <bits/stdc++.h>
#define endl '\n'
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, n, a) for (int i = n; i >= a; i--)
#define LL long long
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
using namespace std;
#define MAXN 500005

int k;
string s, t;

int main()
{
    IOS;
    cin >> k >> s >> t;
    int m = s.size(), n = t.size();
    if(s==t)
    {
        cout << "Yes";
        return 0;
    }
    if(abs(m-n)>1)
    {
        cout << "No";
        return 0;
    }
    if(m==n)
    {
        int cnt = 0;
        rep(i,0,m)
        {
            if(s[i]!=t[i])
                cnt++;
            if(cnt>1)
            {
                cout << "No";
                return 0;
            }
        }
        cout << "Yes";
    }
    if(abs(m-n)==1)
    {
        int cnt = 0;
        int len = max(m, n);
        bool f = 0;
        if(m>n)
        {
            t = t + "0";
            f = 1;
        }
        else
            s = s + "0";
        for (int i = 0, j = 0; i < len && j < len;i++,j++)
        {
            if(s[i]!=t[j])
            {
                cnt++;
                if(f)
                    j--;
                else
                    i--;
            }
        }
        if(cnt==1)
            cout << "Yes";
        else
            cout << "No";
    }
    return 0;
}

D - Diagonal Separation

思路:对题目进行翻译,我们需要构造一个斜腰上点的坐标从上往下不递增的直角梯形。观察发现,如果涂黑的点左上角有涂白的点,那一定无法构造出正确的梯形,所以我们只需查询每个黑点左上方是否有白点。暴力查询的时间复杂度是O(M^2)无法通过此题,于是我们可以将每个点先按从上往下从左往右的顺序排序,而后遍历,并维护一个当前白点的最小纵坐标minwy,每次遇到黑点时查询其纵坐标是否大于minwy即可。

#include <bits/stdc++.h>
#define endl '\n'
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, n, a) for (int i = n; i >= a; i--)
#define LL long long
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
using namespace std;

int n, m;
struct point
{
    int x, y;
    char c;
};

bool cmp(point a, point b)
{
    if(a.x==b.x)
        return a.y < b.y;
    else
        return a.x < b.x;
}

int main()
{
    IOS;
    cin >> n >> m;
    vector<point> p;
    while (m--)
    {
        int x, y;
        char c;
        cin >> x >> y >> c;
        p.push_back({x, y, c});
    }
    sort(p.begin(), p.end(), cmp);
    int minwy=INT_MAX;
    for(auto&it:p)
    {
        if(it.c=='B')
        {
            if(it.y>=minwy)
            {
                cout << "No";
                return 0;
            }
        }
        else
        {
            minwy = min(minwy, it.y);
        }
    }
    cout << "Yes";
    return 0;
}

E - Maximize XOR

思路:题目告诉我们C(n,k)小于10^6,暗示此题可以暴力搜索解决。注意到,该dfs算法的时间复杂度是O(k*C(n,k)),当k较大时会超时,所以我们利用C(n,k)==C(n,n-k)的性质,当k>n/2时,去搜索没有选择的元素的组合:由于XOR运算具有自反性,我们先计算所有元素总的异或和xor_all,再将其与搜索到的未选择的元素进行异或运算,得到的结果就是剩下的,即应该原来选的元素的异或和。

#include <bits/stdc++.h>
#define endl '\n'
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, n, a) for (int i = n; i >= a; i--)
#define LL long long
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
using namespace std;

int n, k;
LL a[200005];
LL ans;

void dfs(int u, int rems, LL xor_tmp)
{
    if(rems == 0)
    {
        ans = max(xor_tmp, ans);
        return;
    }
    rep(i,u+1,n)
    {
        dfs(i, rems - 1, xor_tmp ^ a[i]);
    }
}

int main()
{
    IOS;
    cin >> n >> k;
    rep(i,1,n)
    {
        cin >> a[i];
    }
    if(k<n/2)
    {
        dfs(0, k, 0);
    }
    else
    {
        LL xor_all = 0;
        rep(i, 1, n)
        {
            xor_all ^= a[i];
        }
        dfs(0, n - k, xor_all);
    }
    cout << ans;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值