Codeforces Round #611Div3

Codeforces Round #611Div3 解题报告

A. Minutes Before the New Year

  • 直接模拟
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
int T, n;
void solve()
{
    int h, m;
    cin >> h >> m;
    int ans = 0;
    ans += (24 - h - 1) * 60;
    ans += (60 - m);
    cout << ans << endl;
}
int main()
{
    scanf("%d", &T);
    while(T--) solve();
    return 0;
}

B. Candies Division

  • 平分是最好的方案,做不到就往多里加,贪心。
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
int T, n, k;
void solve()
{
    cin >> n >> k;
    if(n%k == 0){
        cout << n << endl;
        return;
    }
    int a = n / k; //每个人a个糖
    int b = n % k;
    if(b <= k / 2) cout << a*k+b << endl;
    else cout << a*k + k / 2 << endl;
}
int main()
{
    scanf("%d", &T);
    while(T--) solve();
    return 0;
}

C. Friends and Gifts

  • 其实题目本意就是让你在序列为0的地方填数字,然后让得到的序列为一个排列,且对应位置上不能出现对应数字。
  • 只需要记录一下哪些数字没出现,之后倒序往里头填就行了。
  • 比如说5 0 0 2 4中1和3没有出现过 ,之后倒着填就是5 3 1 2 4。
  • 但是可能会有出现位置和数字重合的状况,也就是\(a(i)==i\),但也可以发现如果倒序填的话只会有一个位置出现这样的情况,加上一定会出现两个0,交换一下就好了。
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int n, a[maxn];
int vis[maxn];
vector<int> z;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        vis[a[i]] = 1;
        if(a[i] == 0) z.push_back(i);
    }

    int cnt = 1;
    for(int i = n; i >= 1; i--)
    {
        if(a[i]) continue;
        while(vis[cnt]) cnt++;
        a[i] = cnt; vis[cnt] = 1;
    }

    for(int i = 0; i < z.size(); i++)
    {
        int num = z[i];
        if(a[num] == num)
        {
            if(i < z.size()-1) swap(a[num], a[z[i+1]]);
            else swap(a[num], a[z[i-1]]);
            break;
        }
    }

    for(int i = 1; i <= n; i++)
        printf("%d ", a[i]);
    return 0;
}

D. Christmas Trees

  • 贪心。
  • 首先肯定是放在圣诞树左右两边是最好的选择。
  • 输入的将位置放入一个queue中。
  • 然后类似于bfs的思路遍历点的左右即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
queue<int> q;
map<int, int> mp;
int n, m;
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for(int i = 1, x; i <= n; i++)
    {
        cin >> x;
        q.push(x); mp[x] = 0;
    }

    long long res = 0;
    vector<int> ans;
    while(m)
    {
        int p = q.front(); q.pop();
        if(!mp.count(p-1))
        {
            q.push(p-1);
            mp[p-1] = mp[p]+1;
        }
        if(!mp.count(p+1))
        {
            q.push(p+1);
            mp[p+1] = mp[p]+1;
        }
        if(mp[p] > 0)
        {
            ans.push_back(p);
            res += mp[p];
            m--;
        }
    }
    cout << res << endl;
    for(auto x : ans)
        cout << x << " ";
    puts("");
    return 0;
}

E. New Year Parties

  • 这一题我的代码很丑,但也比较好明白。
  • 其实只要贪心挪动就行了。
  • 最小:
    • 如果上一个位置有人,那我就挪到上一个位置。
    • 否则如果下一个位置有人,我就挪到下一个位置上,同时这个位置就不能再移动了。
    • 如果下一个位置没有人但是下下个位置有人,就可以一起挪动到中间的位置。
  • 最大:
    • 如果一个位置有三个人,就占领三个位置。
    • 如果两个人,且上一个位置没有人,就占领前面和当前位置,否则占领当前位置和后一个位置。
    • 如果只有一个人,看前后站人的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn], n;
int vis[maxn];
int vis1[maxn];
int vis2[maxn];
bool mi[maxn];
void get_min()
{
    for(int i = 1; i <= n; i++)
    {
        if(vis1[i] && !mi[i])
        {
            if(vis1[i-1])
            {
                vis1[i-1] += vis1[i];
                vis1[i] = 0;
                mi[i-1] = 1;
            }
            else if(vis1[i+1])
            {
                vis1[i+1] += vis1[i];
                vis1[i] = 0;
                mi[i+1] = 1;
            }
            else if(vis1[i+2] && !mi[i+2])
            {
                vis1[i+1] += vis1[i+2];
                vis1[i+1] += vis1[i];
                vis1[i] = vis1[i+2] = 0;
                mi[i+1] = mi[i] = mi[i+2] = 1;
            }
        }
    } int ans = 0;
    for(int i = 0; i <= n+1; i++)
        if(vis1[i]) ans++;
    cout << ans << " ";
}

void get_max()
{
    for(int i = 1; i <= n; i++)
    {
        if(vis[i])
        {
            int num = vis[i];
            if(num >= 3)
            {
                vis2[i-1]++;
                vis2[i]++;
                vis2[i+1]++;
            }
            else if(num == 2)
            {
                //如果上一个位置没有放
                if(!vis2[i-1])
                {
                    vis2[i-1]++;
                    vis2[i]++;
                }
                else {
                    vis2[i]++;
                    vis2[i+1]++;
                }
            }
            else if(num == 1)
            {
                if(!vis2[i-1]) vis2[i-1]++;
                else if(!vis2[i]) vis2[i]++;
                else vis2[i+1]++;
            }
        }
    }
    int ans = 0;
    for(int i = 0; i <= n+1; i++)
        if(vis2[i]) ans++;
    cout << ans << endl;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        vis[a[i]]++;
        vis1[a[i]]++;
    }
    get_min();
    get_max();
    return 0;
}

F. DIY Garland

题意描述

  • 给定\(n-1\)条线和\(n\)座灯。
  • 有一个灯是源灯,所有电都从这来。

  • 一跟电线连接两个灯,每个灯有自己的编号,亮度为\(2^i\)
  • 灯分为主灯和副灯,电源从主灯来,流向副灯。
  • 每条电线的重要程度为切断这个电线之后不能通电的亮度之和。
  • 按照电线的重要性从大到小给出了\(n-1\)条线的主灯编号,让你从大到小输出每条电线连接的两个灯的序号。

思路

  • 好麻烦的题面...
  • 首先\(n-1\)条线和\(n\)座灯,可以确定这个结构是一棵树。
  • 题目按照电线重要性给出了节点的主灯,那么第一个必然是源灯,因为连接源灯的电线重要性肯定最大。
  • 其次叶子节点一定不是主灯,而且我们知道叶子节点的子树大小为0。(用\(deg\)数组记录子树大小)
  • 所以我们可以先找出所有的叶子节点压入优先队列,之后倒序连接主灯。(因为电线的重要程度是从大到小给出的)。
  • 连接之后将其看成一体,这样主灯子树大小就可以减一了。
  • 当主灯的子树大小减为0时,就变成了叶子节点,加入队列;如此循环往复直到形成一棵树。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int deg[maxn], n, rt;
vector<int> main_lamp;
int main()
{
    scanf("%d", &n);
    scanf("%d", &rt);
    deg[rt]++;
    main_lamp.push_back(rt);
    for(int i = 2, x; i <= n - 1; i++)
    {
        scanf("%d", &x);
        deg[x]++;
        main_lamp.push_back(x);
    }
    priority_queue<int, vector<int>, greater<int> > q;
    for(int i = 1; i <= n; i++)
        if(deg[i] == 0) q.push(i);
    vector<pair<int, int> > ans;
    while(q.size())
    {
        int x = q.top();
        q.pop();
        int y = main_lamp[main_lamp.size()-1];
        main_lamp.pop_back();
        ans.push_back(make_pair(y, x));
        if(ans.size() == n - 1) break;
        deg[y]--;
        if(deg[y] == 0) q.push(y);
    }
    cout << rt << endl;
    for(int i = ans.size()-1; i >= 0; i--)
        cout << ans[i].first << " " << ans[i].second << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zxytxdy/p/12163896.html