round#611 div3

A

  •水

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
int t, h, m, ans;
int main(){
    t = read();
    while(t--){
        h = read();
        m = read();
        if(!h && !m)
            printf("0\n");
        else{
            ans = (23 - h) * 60 + (60 - m);
            printf("%d\n", ans);
        }
    }
}
View Code

B

  •先平分,有多余的在满足条件情况下尽量加进去

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
int t, n, k, ans = 0, up, q;
int main(){
    t = read();
    while(t--){
        ans = 0;
        n = read(), k = read();
        up = (k >> 1);
        q = n % k;
        if(q < up)
            ans = n;
        else
            ans = n - (q - up);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

C

  题意:将数组中的0换成未出现的数字,使数组成为1~n的错排

  •统计没有出现的数字num(统计的时候已经默认升序了),然后倒序填入0的位置

  •若填入时a[num] = num,如果是第一个填入就让当前num与下一个num互换,如果不是第一个填入则先填入,再将a[num]与上一次填入的a[num]交换即可(因为是倒序填入,所以交换后上一填入位置一定满足a[num] ≠ num

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
int n, a[200010], b[200010], c[200010], cnt = 0, k;
bool vis[200010];
int main(){
    n = read();
    memset(vis, false, sizeof(vis));
    for(ri i = 1; i <= n; ++i){
        a[i] = read();
        vis[a[i]] = 1;
    }
    for(ri i = 1; i <= n ; ++i)
        if(!vis[i])
            b[++cnt] = i;
    k = cnt;
    for(ri i = 1; i <= n; ++i)
        if(!a[i]){
            if(i == b[cnt]){
                if(cnt < k){
                    a[i] = b[cnt];
                    swap(a[i], a[c[cnt + 1]]);
                    cnt--;
                }
                else{
                    int z = b[cnt];
                    b[cnt] = b[cnt - 1];
                    b[cnt - 1] = z;
                    a[i] = b[cnt--];
                }
            }
            else{
                c[cnt] = i;
                a[i] = b[cnt--];
            }
        }
    for(ri i = 1; i <= n; ++i)
        printf("%d ", a[i]);
    return 0;
}
D

  题意:使得人与树的距离之和最小

  •贪心,优先选择距离树最近的点即可,相当于在一个数轴上一轮一轮进行bfs

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
int n, m, x, a[200010], cnt = 0;
long long ans = 0;
map<int, int> mp;
queue<int> q;
int main(){
    n = read(), m = read();
    for(ri i = 1; i <= n; ++i){
        x = read();
        q.push(x);
        mp[x] = 0;
    }
    while(cnt < m){
        int now = q.front();
        q.pop();
        if(!mp.count(now - 1)){
            mp[now - 1] = mp[now] + 1;
            q.push(now - 1);
        }
        if(!mp.count(now + 1)){
            mp[now + 1] = mp[now] + 1;
            q.push(now + 1);
        }
        if(mp[now] > 0){
            a[++cnt] = now;
            ans += mp[now];
        }
    }
    printf("%lld\n", ans);
    for(ri i = 1; i <= m - 1; ++i)
        printf("%d ", a[i]);
    printf("%d\n", a[m]);
    return 0;
}

E

  题意:一个数轴上有一群人,每个人初始位置xi,最终位置可以在xi - 1, xi, xi + 1上,求有人在的点数目的min与max

  •贪心,先排序

  •求min时,人尽可能聚在一起,从头开始安置每一个人,如果在xi - 1, xi, xi + 1有已经安置好的人,则不需要新的聚集点,否则在xi+1处创建新的聚集点(因为是升序安置,所以新聚集点尽可能靠右)

  •求max时,人尽可能散开,从头开始安置每一个人,优先靠左安置,xi - 1, xi, xi + 1,选择可安置的点,若都已经安置有人则继续下一个人

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
#define maxn 200010
int n, a[maxn], vis[maxn], ans = 0;
int main(){
    n = read();
    for(ri i = 1; i <= n; ++i)
        a[i] = read();
    sort(a + 1, a + n + 1);
    for(ri i = 1; i <= n; ++i){
        if(vis[a[i] - 1] || vis[a[i]] || vis[a[i] + 1]){
            continue;
        }
        ans++;
        vis[a[i] + 1] = 1;
    }
    printf("%d ", ans);
    ans = 0;
    memset(vis, 0, sizeof(vis));
    for(ri i = 1; i <= n; ++i){
        if(!vis[a[i] - 1]){
            ans++;
            vis[a[i] - 1] = 1;
            continue;
        }
        if(!vis[a[i]]){
            ans++;
            vis[a[i]] = 1;
            continue; 
        }
        if(!vis[a[i] + 1]){
            ans++;
            vis[a[i] + 1] = 1;
            continue;
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

F

  题意:n - 1个电线,n个灯,每条线两端分为主灯和辅灯,电从主灯流向辅灯,每个灯都有编号,亮度为2i,每个电线有一个重要值,它的重要值为间断该电线之后损失的灯泡亮度之和,已知每个电线的主灯编号,求每个电线两端的灯的编号

  •n - 1个电线,n个灯,显然结构为树

  •重要值最高的灯一个是树根

  •用数组d记录每个主灯儿子节点的个数,没有儿子节点的点即为叶节点

  •将叶节点放入小根堆中,每次堆顶与重要值最小的点连接,该主灯的儿子节点数 - 1

  •主灯的儿子节点数为0时,自己就是叶节点了,放入堆中

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const inline int read(){
    int k = 0, f = 1; char c = getchar();
    for(;!isdigit(c); c = getchar())
        if(c == '-') f = -1;
    for(;isdigit(c); c = getchar())
        k = k * 10 + c - '0';
    return k * f;
}
int n, d[200010], x, root;
vector<int> fa;
priority_queue<int, vector<int>, greater<int> > q;
vector<pair<int, int> > ans;
int main(){
    n = read();
    root = read();
    d[root]++;
    fa.push_back(root);
    for(ri i = 2; i <= n - 1; ++i){
        x = read();
        d[x]++;
        fa.push_back(x);
    }
    for(ri i = 1; i <= n; ++i)
        if(!d[i])
            q.push(i);
    while(!q.empty()){
        int now = q.top();
        q.pop();
        int m = fa[fa.size() - 1];
        fa.pop_back();
        ans.push_back(make_pair(m, now));
        if(ans.size() == n - 1)
            break;
        d[m]--;
        if(!d[m])
            q.push(m);
    }
    printf("%d\n", root);
    for(ri i = ans.size() - 1; i >= 0; --i)
        printf("%d %d\n", ans[i].first, ans[i].second);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kojoker/p/12557502.html