AtCoder Beginner Contest 409

这次的题目有点波折,简单题上连续卡坑,还是心态要放平,慎重决策后再提交

A - Conflict

思路:两个字符串,判断是否存在某位两个字符串均为o

想的时候思路很清晰,写的时候就把条件漏了,这种题都能wa也太不应该了

/*
Author Owen_Q
*/
#include <bits/stdc++.h>

using namespace std;

int main() {
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    bool yes = false;
    string t, a;
    cin >> t >> a;
    for (int i = 0; i < n; i++) {
        if (t[i] == a[i] && t[i] == 'o') {
            yes = true;
        }
    }
    cout << (yes ? "Yes" : "No") << endl;
    return 0;
}

/**
* 4
* xxxx
* xxxx
* No
*/

B - Citation

思路:给定数组,要找出一个最大的数x,使得数组中大于x的数不小于x个。

思路也很清晰,给数组排个序,然后寻找a[i]<i+1条件即为不满足条件的第一个数,那么i就是最终要找的值。

连wa三发也是生无可恋了,第一发将a[i]作为了要求的结果,后来发现其实要求的结果并不一定在数组合中。第二发针对在数组中的场景,发现a[i]=i+1的边界条件未被考虑,第三发针对找不到的场景,应该直接将结果设置为数组大小,特别是第三发wa,我深知考虑到了这种case,但却莫名其妙的想当然认为0就是这种case的正确结果,也是不理解脑子一团混乱。最终这题居然到结束都没想明白,可见有时候当局者迷,陷在里面一点点很弱智的问题都可能困住,还好及时跳过去做后面的题了,要不然结果可能更加惨不忍睹

/*
Author Owen_Q
*/
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e2 + 5;

int main() {
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    int a[MAXN];
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a, a + n, greater<int>());
    int re = n;
    for (int i = 0; i < n; i++) {
        if (a[i] < i + 1) {
            re = i;
            break;
        }
    }
    cout << re << endl;
    return 0;
}

/**
 * 5
 * 1 2 5 7 9
 * 3
 *
 *
 * 3
 * 1 2 5
 * 2
 *
 * 3
 * 6 7 8
 * 3
 */

C - Equilateral Triangle

思路:给定圆周上的点,要判断存在多少个等边三角形。那这就很简单了,首先如果周长不是3的倍数,直接返回0。再记录一下每个点位的位置,将所有点位根据模3的结果分组,每组三个数。将每组三个数的数量相乘,并将不同组的结果相加即为最终值,最后考虑一下结果可能超int,开个长整型即可。

这题其实脑子也糊了一下,一开始只记录每个点位的位置,但没统计每个位置的数量,导致怎么都出不来结果,果然还是受第二题卡顿的影响了。

/*
Author Owen_Q
*/
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 3e5 + 5;

#define ll long long

int a[MAXN];

int main() {
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int l, n;
    cin >> n >> l;
    a[0] = 1;
    int pre = 0;
    for (int i = 1; i < n; i++) {
        int d;
        cin >> d;
        pre = (pre + d) % l;
        a[pre]++;
    }
    if (l % 3 == 0) {
        ll re = 0;
        int div = l / 3;
        for (int i = 0; i < div; i++) {
            ll current = 1;
            for (int j = 0; j < 3; j++) {
                int pos = div * j + i;
                current *= a[pos];
            }
            re += current;
        }
        cout << re << endl;
    } else {
        cout << 0 << endl;
    }
    return 0;
}

D - String Rotation

思路:旋转字符串,寻找字符串的一个子串,将其整体想坐旋转一位,求一个最佳旋转方案,使得旋转后的字典序最小

这就是个简单的贪心,寻找子串的开始和结束位置。开始位置在首个比后一位大的地方,这样可以保证旋转后一定能让字典序减小,而且由于是首位所以一定最小。而结束位置则需要将所有比首位小的字母全都囊括进来,这样可以保证首字母被转到后面后,小的字母一定被往前移动了。

最后手动模拟一下字符串旋转即可

/*
Author Owen_Q
*/
#include <bits/stdc++.h>

using namespace std;

string leftRotate(string s, int st, int en) {
    int len = s.size();
    string newString;
    if (st > 0) {
        newString += s.substr(0, st);
    }
    newString += s.substr(st + 1, en - st - 1);
    newString += s[st];
    if (en < len) {
        newString += s.substr(en, len - en);
    }
    return newString;
}

int main() {
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        string s;
        cin >> s;
        for (int st = 0; st < n - 1; st++) {
            if (s[st] <= s[st + 1]) {
                continue;
            }
            int en = st + 1;
            while (en < n && s[st] >= s[en]) {
                en++;
            }
            if (en > st) {
                s = leftRotate(s, st, en);
                break;
            }
        }
        cout << s << endl;
    }
    return 0;
}

E - Pair Annihilation

思路:在一个树中移动正负离子,树的每个路径有一定权值,要求使得所有离子全都正负中和所需要的最小能量。由于知道最终终局是所有正负离子全都中和,那么这其实移动的过程其实并不重要了,无论是正离子移动还是负离子移动,经过边消耗的能量是相等的。那么这题就从策略题降级为了模拟题。找到所有叶子节点,向上移动,直到移动到根节点。为了避免过度移动,每个节点要等待其所有子节点都移动完之后再开始移动。最后注意一下,结果可能超int,主要是因为最大携带的离子量可能高达10的8次方,因此需要开个long long。

/*
Author Owen_Q
*/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAXN = 2e5 + 5;

int x[MAXN];
bool vis[MAXN];
vector<int> uv[MAXN];
vector<int> uvw[MAXN];
int nextCount[MAXN];

ll moveResult(int now, ll re) {
    int current = x[now];
    bool electrons = current < 0;
    if (electrons) {
        current = -current;
    }
    vis[now] = true;
    int nextSize = uv[now].size();
    for (int i = 0; i < nextSize; i++) {
        int nextNode = uv[now][i];
        if (vis[nextNode]) {
            continue;
        }
        re += ll(uvw[now][i]) * ll(current);

        if (electrons) {
            current = -current;
        }
        x[nextNode] += current;
        nextCount[now]--;
        nextCount[nextNode]--;
        // cout << now << "*" << re << endl;
        if (nextCount[nextNode] == 1) {
            re = moveResult(nextNode, re);
        }
    }
    return re;
}

int main() {
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x[i];
    }
    for (int i = 1; i < n; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        uv[u].push_back(v);
        uv[v].push_back(u);
        uvw[u].push_back(w);
        uvw[v].push_back(w);
        nextCount[u]++;
        nextCount[v]++;
    }
    ll re = 0;
    for (int i = 1; i <= n; i++) {
        if (nextCount[i] == 1) {
            re = moveResult(i, re);
        }
    }
    cout << re << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值