Codeforces Round #633 (Div. 2)【ABCDE】(题解)

目录

涵盖知识点:思维、贪心。

比赛链接:传送门

A - Filling Diamonds

题意: \(n\)个菱形有多少种方法可以拼成一个钻石?
题解: 最终所成图形中只有一个菱形可以立着。所以只有\(n\)中拼法。
Accept Code:

#include <bits/stdc++.h>
using namespace std;

int main(){
    int t;
    cin>>t;
    while(t--) {
        int n;
        cin >> n;
        cout << n << "\n";
    }
    return 0;
}

B - Sorted Adjacent Differences

题意: 排序数组使得相邻之差的绝对值非递减。
题解: 从小到大排序后从中间开始一左一右。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int main(){
    int t;
    cin>>t;
    while(t--) {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)cin>>a[i];
        sort(a,a+n);
        int mid=(n-1)/2;
        cout<<a[mid]<<" ";
        for(int i=1;i<=mid+1;i++){
            if(mid+i<n)cout<<a[mid+i]<<" ";
            if(mid-i>=0)cout<<a[mid-i]<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

C - Powered Addition

题意:\(x\)秒可以使任意个任意数字增加\(2^{x-1}\),问最少几秒使得数列非递减。
题解: 由于二进制特性我们可以讲一个数字增大到任意比他大的值。所以我们只需要找到最大的所需增加值即可。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
int main(){
    int t;
    cin>>t;
    while(t--) {
        int n;
        cin>>n;
        int mx=-inf,res=0;
        for(int i=1,a;i<=n;i++){
            cin>>a;
            res=max(mx-a,res);
            mx=max(a,mx);
        }
        if(res==0)cout<<"0\n";
        else cout<<(int)log2(res)+1<<"\n";
    }
    return 0;
}

D - Edge Weight Assignment

题意:\(n\)节点的数的边赋正值权,使得任意两个叶节点路径上的异或值为\(0\)。求最少和最多赋值种类(即不同数字的个数)
题解: 先考虑最少的情况:如果所有叶子节点距离根的奇偶性相同,那么只要一种就可以了,否则需要\((1,2,3)\)三种,见样例。
然后考虑最多的情况。最理想的条件是每条边都填不同的数字,也就是\(n-1\)种(因为不用是\(1\)\(n-1\),所以一定有解,强行构造就行了),但是考虑到一个节点有多个子节点且都为叶子节点的时候,相邻值必须为相同,所以再减去对应重复的数量即可。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
vector<int> edg[maxn];
int ans;
int c[3], dep[maxn];
void dfs(int u, int fa){
    int cnt = 0;
    for (int v : edg[u]){
        if (v == fa)
            continue;
        dep[v] = dep[u] + 1;
        if (edg[v].size() == 1){
            c[dep[v] & 1]++;
            cnt++;
        }
        else
            dfs(v, u);
    }
    if (cnt >= 2)
        ans -= cnt - 1;
}
int main(){
    int n;
    cin>>n;
    for (int i = 1,x,y; i < n; i++){
        cin>>x>>y;
        edg[x].push_back(y);
        edg[y].push_back(x);
    }
    int root;
    for (int i = 1; i <= n; i++) {
        if (edg[i].size() > 1) {
            root = i;
            break;
        }
    }
    ans = n - 1;
    dfs(root, 0);
    printf("%d %d\n", c[0] && c[1] ? 3 : 1, ans);
    return 0;
}

E - Perfect Triples

题意: 一个初始为空的无限长的序列\(S\)满足以下条件:

  1. 每次加入一个三元组\((a,b,c)\)
  2. \(a,b,c\)都不在\(S\)中。
  3. \(a\oplus b\oplus c=0\)
  4. 该三元组是所有满足条件中字典序最小的。

现在要求该序列的第\(n\)个数字。
题解: 三元组\((1,2,3)\)能够满足异或值为\(0\)。那么在四进制下,保证每一位都是\(1,2,3\)即可。实现起来就是把二进制两位两位地合并起来写就行了。找到规律以后实现难度应该不大。具体打表的规律看这里:传送门
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[4] = {0, 2, 3, 1};
ll B(ll a) { return (a == 1) ? 2 : f[a & 3] | B(a >> 2) << 2; }
int main(){
    int t;
    cin>>t;
    while (t--){
        ll n, A[3];
        cin>>n;
        ll d = 1;
        for (; n >= d; d <<= 2);
        d >>= 2;
        A[0] = d | ((n - d) / 3);
        A[1] = B(A[0]);
        A[2] = A[0] ^ A[1];
        cout<<A[(n - d) % 3]<<"\n";
    }
}

猜你喜欢

转载自www.cnblogs.com/charles1999/p/12690690.html