codeforces Round 646(div. 2)
A、Odd Selection
题意:
$n$个数选$x$个数能不能使它们的和是奇数。
题解:
按奇偶分一波情况就行。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 1e5 + 5; 5 void solve() 6 { 7 int n, x, a; 8 scanf("%d%d", &n, &x); 9 int odd = 0; 10 for (int i = 1; i <= n; ++i) 11 { 12 scanf("%d", &a); 13 if (a % 2) 14 ++odd; 15 } 16 int even = n - odd; 17 if (!odd) 18 printf("No\n"); 19 else if (x == n && odd % 2 == 0) 20 printf("No\n"); 21 else if (!even && x % 2 == 0) 22 printf("No\n"); 23 else 24 printf("Yes\n"); 25 } 26 int main() 27 { 28 int T; 29 scanf("%d", &T); 30 while (T--) 31 solve(); 32 return 0; 33 }
B、Subsequence Hate
题意:
改变最少的位置使得$01$串没有$010$和$101$子序列
题解:
只有$4$可能,处理前缀和然后枚举位置
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e3 + 5; 4 char s[N]; 5 int pre[N]; 6 void solve() 7 { 8 scanf("%s", s + 1); 9 int n = strlen(s + 1); 10 for (int i = 1; i <= n; ++i) 11 pre[i] = pre[i - 1] + s[i] - '0'; 12 int ans = N; 13 for (int i = 0; i <= n; ++i) 14 { 15 ans = min(ans, i - pre[i] + pre[n] - pre[i]); 16 ans = min(ans, pre[i] + n - i - (pre[n] - pre[i])); 17 } 18 printf("%d\n", ans); 19 } 20 int main() 21 { 22 int T; 23 scanf("%d", &T); 24 while (T--) 25 solve(); 26 return 0; 27 }
C、Game On Leaves
题意:
无根树,每次只能删叶子,先删$x$的胜,问最优策略下谁胜
题解:
考虑最终决定胜负时只会剩下$2$个结点,所以就可以考虑谁会到这个状态
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5 + 5; 4 int deg[N]; 5 void solve() 6 { 7 int n, x; 8 scanf("%d%d", &n, &x); 9 memset(deg, 0, sizeof(deg[0]) * (n + 1)); 10 for (int i = 1; i < n; ++i) 11 { 12 int u, v; 13 scanf("%d%d", &u, &v); 14 ++deg[u], ++deg[v]; 15 } 16 if (deg[x] <= 1) 17 { 18 printf("Ayush\n"); 19 return; 20 } 21 printf("%s", n % 2 ? "Ashish\n" : "Ayush\n"); 22 } 23 int main() 24 { 25 int T; 26 scanf("%d", &T); 27 while (T--) 28 solve(); 29 return 0; 30 }
D、Guess The Maximums
题意:
看不懂$QAQ$
题解:
不会$QAQ$
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e3 + 5; 4 int query(int l, int r) 5 { 6 printf("? %d ", r - l + 1); 7 for (int i = l; i <= r; ++i) 8 printf("%d%c", i, " \n"[i == r]); 9 fflush(stdout); 10 int res = 0; 11 scanf("%d", &res); 12 return res; 13 } 14 int col[N], tmp[N]; 15 void solve() 16 { 17 int n, k, a, b; 18 scanf("%d%d", &n, &k); 19 memset(col, -1, sizeof(col[0]) * (n + 1)); 20 for (int i = 1; i <= k; ++i) 21 { 22 scanf("%d", &a); 23 for (int j = 1; j <= a; ++j) 24 { 25 scanf("%d", &b); 26 col[b] = i; 27 } 28 } 29 int maxn = query(1, n); 30 int l = 1, r = n; 31 int maxpos = 0; 32 while (1) 33 { 34 int mid = (l + r) >> 1; 35 if (l == mid) 36 { 37 if (query(l, mid) == maxn) 38 maxpos = l; 39 else 40 maxpos = r; 41 break; 42 } 43 if (query(l, mid) == maxn) 44 r = mid; 45 else 46 l = mid + 1; 47 } 48 if (col[maxpos] == -1) 49 { 50 printf("! "); 51 for (int i = 1; i <= k; ++i) 52 printf("%d%c", maxn, " \n"[i == k]); 53 fflush(stdout); 54 char s[20]; 55 scanf("%s", s); 56 return; 57 } 58 int top = 0; 59 for (int i = 1; i <= n; ++i) 60 if (col[i] != col[maxpos]) 61 tmp[++top] = i; 62 printf("? %d ", top); 63 for (int i = 1; i <= top; ++i) 64 printf("%d%c", tmp[i], " \n"[i == top]); 65 fflush(stdout); 66 int res = 0; 67 scanf("%d", &res); 68 printf("! "); 69 for (int i = 1; i < col[maxpos]; ++i) 70 printf("%d ", maxn); 71 printf("%d ", res); 72 for (int i = col[maxpos] + 1; i <= k; ++i) 73 printf("%d%c", maxn, " \n"[i == k]); 74 fflush(stdout); 75 char s[20]; 76 scanf("%s", s); 77 } 78 int main() 79 { 80 int T; 81 scanf("%d", &T); 82 while (T--) 83 solve(); 84 return 0; 85 }
E、Tree Shuffling
题意:
根为$1$的树,每个点有$a,b,c$三个值,分别代表这个点的代价,这个点的初始颜色,这个点的目标颜色,颜色只有黑和白。对于每个点,我们可以在以它为根的子树中任意选择一些点,将它们的颜色任意分配,代价是这个点代价$\times$点数。求把整棵树变成目标颜色的最小代价,或者输出$-1$表示不可能。
题解:
显然更换以某个点为根的子树的点时,代价是根和它的祖先的代价的最小值。然后更新完之后回溯时要减去这棵子树中更新的。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 2e5 + 5; 5 vector<int> G[N]; 6 int minn[N]; 7 ll a[N], ans; 8 int b[N], c[N]; 9 pair<ll, ll> dfs(int u, int fa, ll cost) 10 { 11 pair<ll, ll> now; 12 if (b[u] != c[u]) 13 { 14 now.first += b[u]; 15 now.second += c[u]; 16 } 17 for (auto i : G[u]) 18 if (i != fa) 19 { 20 pair<ll, ll> nxt = dfs(i, u, min(a[i], cost)); 21 now.first += nxt.first; 22 now.second += nxt.second; 23 } 24 int d = min(now.first, now.second); 25 ans += 2 * d * cost; 26 now.first -= d; 27 now.second -= d; 28 return now; 29 } 30 int main() 31 { 32 int n; 33 scanf("%d", &n); 34 for (int i = 1; i <= n; ++i) 35 scanf("%lld%d%d", &a[i], &b[i], &c[i]); 36 ll sum = 0; 37 for (int i = 1; i < n; ++i) 38 { 39 int u, v; 40 scanf("%d%d", &u, &v); 41 G[u].push_back(v); 42 G[v].push_back(u); 43 } 44 for (int i = 1; i <= n; ++i) 45 sum += b[i] - c[i]; 46 if (sum) 47 return printf("-1\n"), 0; 48 dfs(1, 0, a[1]); 49 printf("%lld\n", ans); 50 return 0; 51 }