Codeforces Round 998 (Div. 3) A - E

链接:Codeforces Round 998 (Div. 3)

A:Fibonacciness

大意:

       a1 - a5,给定1 2 4 5,求最大满足a[i + 2] = a[i + 1] + a[i]的i的数

思路:

       a3也不管情况重复没重复,三种情况满足情况取最后结果最大值即可

        后来发现随便填两种就行,不过要的是速度,细想浪费时间

代码:

#include <bits/stdc++.h>

using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =


void solve()
{
    vi a(10);
    cin >> a[1] >> a[2] >> a[4] >> a[5];

    a[3] = a[1] + a[2];
    int ans = 0, tmp = 0;
    for (int i = 3; i <= 5; i++)
        if (a[i - 2] + a[i - 1] == a[i])tmp++;
    ans = max(ans, tmp);

    tmp = 0;
    a[3] = a[4] - a[2];
    for (int i = 3; i <= 5; i++)
        if (a[i - 2] + a[i - 1] == a[i])tmp++;
    ans = max(ans, tmp);

    tmp = 0;
    a[3] = a[5] - a[4];
    for (int i = 3; i <= 5; i++)
        if (a[i - 2] + a[i - 1] == a[i])tmp++;
    ans = max(ans, tmp);

    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

 B:Farmer John's Card Game

大意:

        卡牌游戏,给定n头牛,每头牛m张牌,牛顺序出牌m轮,求是否存在一个顺序,使得每次出的牌都比上次的牌大。如果不能出完,输出-1,否则输出顺序。

思路:

        给每头牛的牌从小到大排序,然后以第一张牌大小为顺序,如果有牛第一张牌大于等于n,就直接-1。

        然后记录一个上次的牌大小,依次遍历即可。

代码:

#include <bits/stdc++.h>

using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =


void solve()
{
    int n, m;
    cin >> n >> m;
    vvi a(n + 1, vi(m));

    for (int i = 1; i <= n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];

    for (int i = 1; i <= n; i++)
        sort(a[i].begin(), a[i].end());

    vi p(n + 1);
    for (int i = 1; i <= n; i++)
        if (a[i][0] < n)
            p[a[i][0] + 1] = i;
        else
        {
            cout << -1 << endl;
            return;
        }

    int last = -1;
    for(int i = 0; i < m; i ++)
        for (int j = 1; j <= n; j++)
        {
            if (a[p[j]][i] < last)
            {
                cout << -1 << endl;
                return;
            }
            else last = a[p[j]][i];
        }

    for (int i = 1; i <= n; i++)cout << p[i] << ' ';
    cout << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

C:Game of Mathletes

大意:

        A和B玩游戏,黑板上n(n为偶数)个数,A擦掉一个,B擦掉一个,进行n/2轮,每轮若两人擦掉的数的和为k,分数+1,否则分数不变,A想分最小,B想分最大。求最大分。

思路:

        因为偶数个数,所以就算按照最佳策略,Alice也没法改变结果。最后最多能凑出几个答案就是几个。

代码:

#include <bits/stdc++.h>

using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =


void solve()
{
    int n, k;cin >> n >> k;
    vi a(n);
    for (int i = 0; i < n; i++)cin >> a[i];
    
    unordered_map<int, int> mp;
    for (int i = 0; i < n; i++)mp[a[i]]++;

    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
    
    int ans = 0;
    for (auto i : a)
    {
        if (i < k / 2 && mp.count(k - i))ans += min(mp[i], mp[k - i]);
        else if (i == k / 2)
        {
            if (k % 2 == 0)ans += mp[i] / 2;
            else if (mp.count(k - i))ans += min(mp[i], mp[k - i]);
        }
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

D:Subtract Min Sort

大意:

       一个数组,可以进行任意次操作,每次操作相邻两个数减去这两个数的较小值,问问是否可以使得数组非递减。

思路:

        每次操作,两个数就至少有一个变成0,那么如果后面的不是非递减,前面的就需要全为0

        而且观察到,(我蒙的,反证蒙的)从前往后依次进行操作,则最后得到的序列如果非递减就非递减,不是就不行。

代码:

#include <bits/stdc++.h>

using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =


void solve()
{
    int n;cin >> n;
    vi a(n);
    for (int i = 0; i < n; i++)cin >> a[i];

    for (int i = 1; i < n; i++)
    {
        int num = min(a[i], a[i - 1]);
        a[i] -= num;
        a[i - 1] -= num;
    }
        
    for(int i = 1; i < n; i ++)
        if (a[i] < a[i - 1])
        {
            cout << "NO" << endl;
            return;
        }
    cout << "YES" << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

E:Graph Composition

大意:

        给两个图,对第一个图可以进行加边或者减边操作,求最少操作数,使得两个图的任意两点连通性相同。

思路:

        任意两点连通性相同,首先图2的连通性是已知的,我们需要对图1加边减边,

        首先考虑减边,因为加边再减边好像不太好做。看图1中哪些边是必须要去掉的,遍历图1的边,如果两点在图2中是连着的,那么这个边就可以留下,如果没连着,这个边就一定不能要。

        操作完后就得到了新的图1,图1有的边图2一定有,图2没的边图1一定没有。

        然后就考虑加边,我们需要找到图2连通集合,把图2有图1没有的边加上去。

        这样图2有的图1一定有,图2没的图1一定没有.

        使用并查集实现即可。

代码:

#include <bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =

int find(vi &p, int x)
{
    if (p[x] != x)p[x] = find(p, p[x]);
    return p[x];
}

void solve() 
{
    int n, m, k;
    cin >> n >> m >> k;

    vii s1(m), s2(k); // 边
    vi p1(n + 1), p2(n + 1);
    for (int i = 1; i <= n; i++)
        p1[i] = p2[i] = i;

    for (int i = 0; i < m; i++)
        cin >> s1[i].ff >> s1[i].ss;
    for (int i = 0; i < k; i++)
        cin >> s2[i].ff >> s2[i].ss;

    for (int i = 0; i < k; i++) // 图2集合确定
        p2[find(p2, s2[i].ff)] = find(p2, s2[i].ss);

    int ans = 0;

    // 删边操作,这里在加边时进行,删除的不加即可
    for (auto& [x, y] : s1)
    {
        if (find(p2, x) != find(p2, y))ans++;
        else p1[find(p1, x)] = find(p1, y);
    }

    //同一集合下元素
    unordered_map<int, vi> mp;
    for (int i = 1; i <= n; i++)mp[find(p2, i)].push_back(i);//根节点下的元素

    for(int i = 1; i <= n; i ++)
        for (auto& x : mp[i])
            if (find(p1, x) != find(p1, i)) //不在就加边
            {
                ans++;
                p1[find(p1, x)] = find(p1, i);
            }

    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值