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
思路:
一个很直接办法就是暴力枚举负数出现的个数。
- 负数出现了 \(0\) 个;
- 负数出现了 \(2\) 个;
- 负数出现了 \(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;
}
C. Link Cut Centroids
思路:
根据题意可以理解:
把某个点当作根,计算一下以儿子节点为根的子树的大小,取最小的值。
然后每个点都要作为根节点算一遍,再在里面取最小,即是重心。
那么我们 \(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;
}