Codeforces Round 946 (Div. 3)A-G

A. Phone Desktop

题目大意:给出x个1*1和y个2*2的方块,问用几个3*5的方块能够装下。

分析:很明显3*5最多装2个2*2的方块,所以我们考虑先装2*2的,然后1*1的填进去,有多的话再用3*5直接装1*1的。

代码:

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

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

void solve()
{
    int n, m;
    cin >> n >> m;
    int res = m / 2;
    int sum = res * 7;//sum用来存当前有多少可以供1*1使用的
    if (m & 1)
    {
        res ++ ;
        sum += 11;
    }
    if (sum < n)
    {
        n -= sum;
        res += n / 15;
        if (n % 15) res ++ ;
    }
    cout << res << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

B. Symmetric Encoding

题目大意:
给出一个字符串s, 将s中出现的字母按大小排列,然后将第一个换成最后一个,第二个换成倒数第二个以此类推。

分析:模拟即可

代码:

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

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    bool f[300] = {0};
    for (int i = 0; i < s.size(); i ++ )
    {
        if (!f[s[i]]) f[s[i]] = 1;
    }
    string r;
    for (int i = 0; i < 300; i ++ )
        if (f[i]) r += (char)i;

    map<char, char> mp;
    for (int i = 0; i < r.size(); i ++ )
    {
        mp[r[i]] = r[r.size() - i - 1];
    }

    for (int i = 0; i < s.size(); i ++ )
        cout << mp[s[i]];
    cout << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

C. Beautiful Triple Pairs

题目大意:

给出数组a, 长度为n,其中有n-2个三元组[a[j], a[j + 1], a[j + 2]], 求有多少对三元组满足只有其中两个值相等。

分析:

首先可见三元组的个数并不多, 所以我们可以考虑记录下第一个,第二个相等的个数s1,第一个,第三个相等的个数s2, 第二个,第三个相等的个数s3, 然后在记录全部相等的个数s,那么[x, y, z]能够给答案做出的贡献为s1 + s2 + s3 - 3 * s, 考虑到某一对答案交换顺序还是这一对,所以我们可以从左向右维护s, s1, s2, s3, 或者全部相加除2, 这里我是从左向右维护。

代码:

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

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int, int, int> t3;

const int N = 2e5 + 10;

ll a[N];

void solve()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++ )
        cin >> a[i];
    
    map<t3, ll> mp;// 存三元组[x, y, z]的个数
    map<t3, ll> mp2;//存[x, y, 0], [x, 0, z], [0,, y, z]的个数
    for (ll i = 2; i < n; i ++ )
    {
        mp[{a[i - 2], a[i - 1], a[i]}] ++ ;
        mp2[{a[i - 2], a[i - 1], 0}] ++ ;
        mp2[{a[i - 2], 0, a[i]}] ++ ;
        mp2[{0, a[i - 1], a[i]}] ++ ;
    }

    ll res = 0;
    for (int i = 2; i < n; i ++ )
    {
        res += mp2[{a[i - 2], a[i - 1], 0}];
        res += mp2[{a[i - 2], 0, a[i]}];
        res += mp2[{0, a[i - 1], a[i]}];
        res -= 3 * mp[{a[i - 2], a[i - 1], a[i]}];
        mp[{a[i - 2], a[i - 1], a[i]}] -- ;
        mp2[{a[i - 2], a[i - 1], 0}] -- ;
        mp2[{a[i - 2], 0, a[i]}] -- ;
        mp2[{0, a[i - 1], a[i]}] -- ;
    }
    cout << res << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

D. Ingenuity-2

题目大意:

有两个物品(?), 起始在同一位置, 给出一段操作,分配这一段操作让这两个物品最后的位置相同。(注意要求两个物品必须行动至少一次)

分析:

很显然如果某一轴上的操作数为奇数, 则一定无法完成目标。然后我们可以简单的去思考方法, 那就是将所有操作按类平均分配给两个物品, 即操作为N的平均分等, 然后我们会发现可能会多出一个操作, 此时注意只要全分配给同一个人就可以了, 但是可能会导致某个物品没有行动(这种情况样例有给, 显得简单了?), 可以想到这种情况只有两种, 也就是每种操作出现一次以及某一轴上的正负操作都为1,另一轴上没有, 所以可以特判。

代码:

写的有点shi

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

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    int sx[4] = {0};
    for (int i = 0; i < s.size(); i ++ )
    {
        if (s[i] == 'N') sx[0] ++ ;
        else if (s[i] == 'S') sx[1] ++ ;
        else if (s[i] == 'E') sx[2] ++ ;
        else sx[3] ++ ;
    }
    if ((sx[0] + sx[1] & 1) || (sx[2] + sx[3] & 1) || (sx[0] / 2 == 0 && sx[1] / 2 == 0 && sx[2] / 2 == 0 && sx[3] / 2 == 0 && (sx[0] + sx[1] + sx[2] + sx[3]) < 4))
    {
        cout << "NO" << endl;
        return;
    }
    else if (sx[0] / 2 == 0 && sx[1] / 2 == 0 && sx[2] / 2 == 0 && sx[3] / 2 == 0 && (sx[0] + sx[1] + sx[2] + sx[3]) == 4)
    {
        for (int i = 0; i < s.size(); i ++ )
            if (s[i] == 'N') cout << "H";
            else if (s[i] == 'S') cout << "H";
            else cout << "R";
        cout << endl;
        return;
    }
    {

    }
    int sr[4] = {0};
    for (int i = 0; i < s.size(); i ++ )
    {
        if (s[i] == 'N')
        {
            if (sr[0] == sx[0] / 2) cout << 'H';
            else
            {
                sr[0] ++ ;
                cout << "R";
            }
        }
        else if (s[i] == 'S')
        {
            if (sr[1] == sx[1] / 2) cout << 'H';
            else
            {
                sr[1] ++ ;
                cout << "R";
            }
        }
        else if (s[i] == 'E')
        {
            if (sr[2] == sx[2] / 2) cout << 'H';
            else
            {
                sr[2] ++ ;
                cout << "R";
            }
        }
        else
        {
            if (sr[3] == sx[3] / 2) cout << 'H';
            else
            {
                sr[3] ++ ;
                cout << "R";
            }
        }
    }
    cout << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

E. Money Buys Happiness

题目大意:

每过一个月能获得x元钱, 然后你可以选择是否购买花费为ci,价值为hi的物品, 问n - 1个月后你能获得的最大价值。

分析:

我们读题后会很容易想到选择dp, 但是题目中花费的范围非常大, 而价值的范围却很小, 所以我们可以考虑作dp【i】定义为当价值为i时所需要的最大花费, 由于每月的花费限制, 所以要添加一个if判断是否能进行这次转移。

时间复杂度:mh

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 1e5 + 10;

ll dp[N];
ll c[N], h[N];

void solve()
{
    memset(dp, 0x3f3f, sizeof dp);
    dp[0] = 0;
    ll m, x;
    cin >> m >> x;
    int mx = 0;
    for (ll i = 0; i < m; i ++ )
    {
        cin >> c[i] >> h[i];
        mx += h[i];
    }
    for (ll i = 0; i < m; i ++ )
    {
        for (ll j = mx; j >= h[i]; j -- )
        {
            if (dp[j - h[i]] + c[i] <= x * i)
                dp[j] = min(dp[j], dp[j - h[i]] + c[i]);
        }
    }
    for (ll j = mx; j >= 0; j -- )
        if (dp[j] <= (m - 1) * x)
        {
            cout << j << endl;
            return;
        }
}

int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

G. Money Buys Less Happiness Now

题目大意:是e的改版, 每过一个月能获得x元钱, 然后你可以选择是否购买花费为ci,价值为1的物品, 问n - 1个月后你能获得的最大价值。

分析:很明显的反悔贪心板子题, 没见过的可以学一下反悔贪心。

时间复杂度:nlogn

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

void solve()
{
    priority_queue<int> q;
    int n, m;
    cin >> n >> m;
    int sum = 0, res = 0;
    for (int i = 0; i < n; i ++ )
    {
        int x;
        cin >> x;
        if (x + sum <= i * m)
        {
            sum += x;
            res ++ ;
            q.push(x);
        }
        else if (q.size() && q.top() > x)
        {
            sum -= q.top();
            q.pop();
            sum += x;
            q.push(x);
        }
    }
    cout << res << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

这次还是有很多不必要的wa, 然后赛时被f卡住了没看g, 最后10分钟感觉想不出f就直接看看g,结果一眼反悔贪心, 然后写急了wa3发,虽然最后过了但罚时太多了。然后这场是不是过于简单了?没打过几场不清楚。

补F:

题目大意:两个人在一个棋盘上玩游戏,棋盘中有许多点,他们每次可以切割棋盘的一条边,给出他们是如何操作的,求两个人最终得分。

分析:可以发现点的数量并不多,我们可以考虑预处理所有点排序两次,一次按x从小到大,一次按y从小到大,然后每次操作是维护棋盘的l,r,并根据操作用双指针得出哪些点被包含了,由于可能有点被重复计算,所以我们可以用map判断这个点是否被使用过即可。

时间复杂度:nlogn(logn(map的))

代码:

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

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int N = 2e5 + 10;

pii sx[N], sy[N];

bool cmp(pii a, pii b)
{
    return a.second < b.second;
}

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

    map<pii, bool> mp;
    for (int i = 0; i < n; i ++ )
    {
        int x, y;
        cin >> x >> y;
        sx[i] = {x, y};
        sy[i] = {x, y};
        mp[{x, y}] = 1;
    }

    sort(sx, sx + n);
    sort(sy, sy + n, cmp);

    int lx = 0, rx = a + 1, ly = 0, ry = b + 1;
    int plx = 0, prx = n - 1, ply = 0, pry = n - 1;
    int res[2] = {0};
    for (int i = 0; i < m; i ++ )
    {
        int add = 0, k;
        char op;
        cin >> op >> k;
        if (op == 'U')
        {
            lx += k;
            while (plx <= prx && sx[plx].first <= lx)
            {
                if (mp[sx[plx]])
                {
                    add ++ ;
                    mp[sx[plx]] = 0;
                }
                plx ++ ;
            }
        }
        else if (op == 'D')
        {
            rx -= k;
            while (plx <= prx && sx[prx].first >= rx)
            {
                if (mp[sx[prx]])
                {
                    add ++ ;
                    mp[sx[prx]] = 0;
                }
                prx -- ;
            }
        }
        else if (op == 'L')
        {
            ly += k;
            while (ply <= pry && sy[ply].second <= ly)
            {
                if (mp[sy[ply]])
                {
                    add ++ ;
                    mp[sy[ply]] = 0;
                }
                ply ++ ;
            }
        }
        else
        {
            ry -= k;
            while (ply <= pry && sy[pry].second >= ry)
            {
                if (mp[sy[pry]])
                {
                    add ++ ;
                    mp[sy[pry]] = 0;
                }
                pry -- ;
            }
        }
        res[i & 1] += add;
    }
    cout << res[0] << ' ' << res[1] << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

题解没怎么看懂,但过了几天再看才发现这么简单,赛时就是想不出来😓。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值