Codeforces Round #670 (Div. 2) A - C 解题报告

题目链接

A. Subset Mex

思路:

桶排记录一下每个数出现的次数。从小到大遍历。

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-12 21:33:31
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-12 21:58:48
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f;
inline void input(char &a  ) { cin >> a;          }
inline void input(string &a) { cin >> a;          }
inline void input(char * a ) { scanf("%s", a);    }
inline void input(int &a   ) { scanf("%d", &a);   }
inline void input(ll &a    ) { scanf("%lld", &a); }
inline void input(double &a) { scanf("%lf", &a);  }
inline void output(ll a    ) { printf("%lld\n",a);}
inline void output(int a   ) { printf("%d\n",a);  }
inline void output(char a  ) { printf("%c\n",a);  }
inline void output(char * a) { printf("%s\n",a);  }
inline void output(string a) { cout << a << endl; }
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e2 + 10;

int arr[N];

int main(){

    int t; input(t);
    while(t --){
        int n; input(n);
        memset(arr, 0, sizeof arr);
        for(int i = 1; i <= n; i ++){
            int x; input(x);
            arr[x] ++;
        }
        int a = -1, b = -1;
        for(int i = 0; i <= 100; i ++){
            if(a != -1 && b != -1) break;
            if(arr[i] == 0){
                if(a == -1) a = i;
                if(b == -1) b = i;
            } else if(arr[i] == 1){
                if(a != -1 || b != -1) continue;
                if(a == -1) { a = i; continue; }
                if(b == -1) { b = i; }
            }
        }
        int mx = 0;
        for(int i = 0; i <= 100; i ++) if(arr[i] == 0) { mx = i; break; }
        //printf("a = %d b = %d\n", a, b);
        output(max(mx, a + b));
    }
    return 0;
}

B. Maximum Product

思路:

一个很直接办法就是暴力枚举负数出现的个数。

  1. 负数出现了 \(0\) 个;
  2. 负数出现了 \(2\) 个;
  3. 负数出现了 \(4\) 个;
  4. 如果上面都不能满足,就说明答案 \(\leq 0\) 的。

注:(代码很丑,勿看)

代码:
/*
 * @Author       : nonameless
 * @Date         : 2020-09-12 22:02:46
 * @LastEditors  : nonameless
 * @LastEditTime : 2020-09-12 23:36:37
 */
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline void input(char &a  ) { cin >> a;          }
inline void input(string &a) { cin >> a;          }
inline void input(char * a ) { scanf("%s", a);    }
inline void input(int &a   ) { scanf("%d", &a);   }
inline void input(ll &a    ) { scanf("%lld", &a); }
inline void input(double &a) { scanf("%lf", &a);  }
inline void output(ll a    ) { printf("%lld\n",a);}
inline void output(int a   ) { printf("%d\n",a);  }
inline void output(char a  ) { printf("%c\n",a);  }
inline void output(char * a) { printf("%s\n",a);  }
inline void output(string a) { cout << a << endl; }
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e5 + 10;

ll a[N];

struct st{
    ll v;
    int f;
}b[N];

bool cmp(st p, st q) { return p.v > q.v; }

int main(){

    int t; cin >> t; 
    while(t --){
        int n; cin >> n;
        int cd = 0;
        for(int i = 1; i <= n; i ++){
            cin >> a[i];
            if(a[i] < 0) {
                b[++cd].v = -a[i];
                b[cd].f = 0;
            } else if(a[i] > 0){
                b[++cd].v = a[i];
                b[cd].f = 1;
            }
            a[i] = abs(a[i]);
        }
        sort(b + 1, b + cd + 1, cmp);
        ll ans = -1e18, tmp1 = 1, tmp2 = 1, tmp3 = 1, tmp4 = 1;
        int mark = 0;
        for(int i = 1, j = 0; i <= cd; i ++){
            if(b[i].f){
                tmp1 *= b[i].v;
                j ++;
            }
            if(j == 5) { mark = 1; break; }
        }
        if(mark) ans = max(ans, tmp1);
        mark = 0;
        for(int i = 1, j = 0, k = 0; i <= cd; i ++){
            if(b[i].f && j < 3) {
                tmp2 *= b[i].v;
                j ++;
            } else if(b[i].f == 0 && k < 2){
                tmp2 *= b[i].v;
                k ++;
            }
            if(j == 3 && k == 2) { mark = 1; break; }
        }
        if(mark) { ans = max(ans, tmp2); mark = 0; }
        for(int i = 1, j = 0, k = 0; i <= cd; i ++){
            if(b[i].f && j < 1){
                tmp3 *= b[i].v;
                j ++;
            } else if(!b[i].f && k < 4){
                tmp3 *= b[i].v;
                k ++;
            }
            if(j == 1 && k == 4) { mark = 1; break; }
        }
        if(mark) { ans = max(ans, tmp3); mark = 0; }
        sort(a + 1, a + n + 1);
        for(int i = 1; i <= 5; i ++)  tmp4 *= a[i];
        ans = max(ans, -tmp4);
        cout << ans << endl;
    }
    return 0;
}
思路:

根据题意可以理解:

把某个点当作根,计算一下以儿子节点为根的子树的大小,取最小的值。

然后每个点都要作为根节点算一遍,再在里面取最小,即是重心。

那么我们 \(dfs\) 一遍就可以计算出来。

注(一个颗树最多有两个重心,如果有就一定相连)

  • 一个重心就任意删去一条与重心相连的边
  • 两个重心就删去某个重心的儿子节点(该节点不是重心),然后该节点与另一个重心相连。
代码:
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI  = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF  = 0x3f3f3f3f3f3f3f3f;
inline void input(char &a  ) { cin >> a;          }
inline void input(string &a) { cin >> a;          }
inline void input(char * a ) { scanf("%s", a);    }
inline void input(int &a   ) { scanf("%d", &a);   }
inline void input(ll &a    ) { scanf("%lld", &a); }
inline void input(double &a) { scanf("%lf", &a);  }
inline void output(ll a    ) { printf("%lld\n",a);}
inline void output(int a   ) { printf("%d\n",a);  }
inline void output(char a  ) { printf("%c\n",a);  }
inline void output(char * a) { printf("%s\n",a);  }
inline void output(string a) { cout << a << endl; }
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll  gcd(ll  a, ll  b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }

const int N = 1e5 + 10;

vector<int> g[N];

int n;
int cnt[N], sz[N];

void dfs(int u, int fa){
    sz[u] = 1;
    for(auto it : g[u]){
        if(it == fa) continue;
        dfs(it, u);
        sz[u] += sz[it];
        cnt[u] = max(cnt[u], sz[it]);
    }
    cnt[u] = max(cnt[u], n - sz[u]);
}

int main(){

    int t; input(t);
    while(t --){
        input(n);
        memset(cnt, 0, sizeof cnt);
        memset(sz, 0, sizeof sz);
        for(int i = 1; i < n; i ++){
            int u, v; input(u); input(v);
            g[u].pb(v); g[v].pb(u);
        }
        dfs(1, 0);
        int mn = *min_element(cnt + 1, cnt + n + 1);
        int a = 0, b = 0;
        for(int i = 1; i <= n; i ++){
            if(cnt[i] == mn){
                if(a) b = i;
                else  a = i;
            }
        }
        if(b == 0){
            int t = g[a][0];
            printf("%d %d\n", a, t);
            printf("%d %d\n", a, t);
        } else{
            int t;
            for(auto it : g[b]) if(it != a)  { t = it; break; }
            printf("%d %d\n", b, t);
            printf("%d %d\n", a, t);
        }
        for(int i = 1; i <= n; i ++) g[i].clear();
    }

    
    return 0;
}

posted @ 2020-09-13 14:26  nonameless  阅读(143)  评论(0编辑  收藏  举报