A. Odd Selection
网址:https://codeforces.com/contest/1363/problem/A
Shubham has an array a of size n, and wants to select exactly x elements from it, such that their sum is odd. These elements do not have to be consecutive. The elements of the array are not guaranteed to be distinct.
Tell him whether he can do so.
Input
The first line of the input contains a single integer t (1≤t≤100) — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers n and x (1≤x≤n≤1000) — the length of the array and the number of elements you need to choose.
The next line of each test case contains n integers a1,a2,…,an (1≤ai≤1000) — elements of the array.
Output
For each test case, print "Yes" or "No" depending on whether it is possible to choose x elements such that their sum is odd.
You may print every letter in any case you want.
Example
input
5
1 1
999
1 1
1000
2 1
51 50
2 2
51 50
3 3
101 102 103
output
Yes
No
Yes
Yes
No
Note
For 1st case: We must select element 999, and the sum is odd.
For 2nd case: We must select element 1000, so overall sum is not odd.
For 3rd case: We can select element 51.
For 4th case: We must select both elements 50 and 51 — so overall sum is odd.
For 5th case: We must select all elements — but overall sum is not odd.
果然考察算法基本功。
当时做麻烦了。其实不妨考虑:和为奇数时累加奇数的个数k必为奇数。统计该序列中奇数的个数,以及偶数的个数。分别记为odd_num,even_num;
每次选择k个奇数,当x - k <= even_num时存在。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1000 + 5;
int n, x, a[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
memset(a, 0, sizeof(a));
int odd_num = 0, even_num = 0;
scanf("%d %d", &n, &x);
for(int i = 1; i <= n; ++ i)
{
scanf("%d", &a[i]);
if(a[i] & 1) ++ odd_num;
else ++ even_num;
}
bool ok = 0;
for(int i = 1; i <= min(x, odd_num); i += 2)
{
if(even_num >= x - i)
{
ok = 1;
puts("Yes");
break;
}
}
if(ok == false) puts("No");
}
return 0;
}
B. Subsequence Hate
网址:https://codeforces.com/contest/1363/problem/B
Shubham has a binary string s. A binary string is a string containing only characters "0" and "1".
He can perform the following operation on the string any amount of times:
Select an index of the string, and flip the character at that index. This means, if the character was "0", it becomes "1", and vice versa.
A string is called good if it does not contain "010" or "101" as a subsequence — for instance, "1001" contains "101" as a subsequence, hence it is not a good string, while "1000" doesn't contain neither "010" nor "101" as subsequences, so it is a good string.
What is the minimum number of operations he will have to perform, so that the string becomes good? It can be shown that with these operations we can make any string good.
A string a is a subsequence of a string b if a can be obtained from b by deletion of several (possibly, zero or all) characters.
Input
The first line of the input contains a single integer t (1≤t≤100) — the number of test cases.
Each of the next t lines contains a binary string s (1≤|s|≤1000).
Output
For every string, output the minimum number of operations required to make it good.
Example
input
7
001
100
101
010
0
1
001100
output
0
0
1
1
0
0
2
Note
In test cases 1, 2, 5, 6 no operations are required since they are already good strings.
For the 3rd test case: "001" can be achieved by flipping the first character — and is one of the possible ways to get a good string.
For the 4th test case: "000" can be achieved by flipping the second character — and is one of the possible ways to get a good string.
For the 7th test case: "000000" can be achieved by flipping the third and fourth characters — and is one of the possible ways to get a good string.
题目让我们将序列分两半。那就枚举每一个位置为界线取最值。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 1000 + 10, INF = 1 << 30;
char s[maxn];
int sum, L_sum[maxn], R_sum[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
int n;
memset(L_sum, 0, sizeof(L_sum));
memset(R_sum, 0, sizeof(R_sum));
scanf("%s", (s + 1));
n = strlen(s + 1);
int sum = INF;
for(int i = 1; i <= n; ++ i)
{
L_sum[i] = L_sum[i - 1] + s[i] - '0';
}
for(int i = n; i; -- i)
{
R_sum[i] = R_sum[i + 1] + s[i] - '0';
}
for(int i = 1; i <= n; ++ i)
{
sum = min(sum, min(L_sum[i], i - L_sum[i]) + min(R_sum[i + 1], n - i - R_sum[i + 1]));
}
printf("%d
", sum);
}
return 0;
}
C. Game On Leaves
网址:https://codeforces.com/contest/1363/problem/C
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Ayush and Ashish play a game on an unrooted tree consisting of n nodes numbered 1 to n. Players make the following move in turns:
- Select any leaf node in the tree and remove it together with any edge which has this node as one of its endpoints. A leaf node is a node with degree less than or equal to 1.
A tree is a connected undirected graph without cycles.
There is a special node numbered x. The player who removes this node wins the game.
Ayush moves first. Determine the winner of the game if each player plays optimally.
Input
The first line of the input contains a single integer t (1≤t≤10) — the number of testcases. The description of the test cases follows.
The first line of each testcase contains two integers n and x (1≤n≤1000,1≤x≤n) — the number of nodes in the tree and the special node respectively.
Each of the next n−1 lines contain two integers u, v (1≤u,v≤n, u≠v), meaning that there is an edge between nodes u and v in the tree.
Output
For every test case, if Ayush wins the game, print "Ayush", otherwise print "Ashish" (without quotes).
Examples
input
1
3 1
2 1
3 1
output
Ashish
input
1
3 2
1 2
1 3
output
Ayush
Note
For the 1st test case, Ayush can only remove node 2 or 3, after which node 1 becomes a leaf node and Ashish can remove it in his turn.
For the 2nd test case, Ayush can remove node 2 in the first move itself.
这道题首先从特殊情况入手:
- 当节点x为叶子节点时,先手比赢;
- 当节点x度数大于1时,不管怎样,只有当它度数为1时才可以判定。最优策略等价于每人不进行能够使节点x度数为1的操作(除了万不得已)。我们可以通过n的奇偶性判断谁最后胜利。
- 即当n为奇数的时候,后手必赢。同理,不加赘述了。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 1000 + 5;
int n, x, deg[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%d %d", &n, &x);
int u, v;
memset(deg, 0, sizeof(deg));
for(int i = 1; i < n; ++ i)
{
scanf("%d %d", &u, &v);
++ deg[u];
++ deg[v];
}
if(deg[x] < 2) puts("Ayush");
else if(n & 1) puts("Ashish");
else puts("Ayush");
}
return 0;
}
D. Guess The Maximums
网址:https://codeforces.com/contest/1363/problem/D
- 补
E. Tree Shuffling
网址:https://codeforces.com/contest/1363/problem/E
Ashish has a tree consisting of n nodes numbered 1 to n rooted at node 1. The i-th node in the tree has a cost ai, and binary digit bi is written in it. He wants to have binary digit ci written in the i-th node in the end.
To achieve this, he can perform the following operation any number of times:
Select any k nodes from the subtree of any node u, and shuffle the digits in these nodes as he wishes, incurring a cost of k⋅au. Here, he can choose k ranging from 1 to the size of the subtree of u.
He wants to perform the operations in such a way that every node finally has the digit corresponding to its target.
Help him find the minimum total cost he needs to spend so that after all the operations, every node u has digit cu written in it, or determine that it is impossible.
Input
First line contains a single integer n ((1≤n≤2⋅10^5)) denoting the number of nodes in the tree.
i-th line of the next n lines contains 3 space-separated integers ai, bi, ci ((1≤ai≤10^9,0≤bi,ci≤1)) — the cost of the i-th node, its initial digit and its goal digit.
Each of the next n−1 lines contain two integers u, v (1≤u,v≤n, u≠v), meaning that there is an edge between nodes u and v in the tree.
Output
Print the minimum total cost to make every node reach its target digit, and −1 if it is impossible.
Examples
input
5
1 0 1
20 1 0
300 0 1
4000 0 0
50000 1 0
1 2
2 3
2 4
1 5
output
4
input
5
10000 0 1
2000 1 0
300 0 1
40 0 0
1 1 0
1 2
2 3
2 4
1 5
output
24000
input
2
109 0 1
205 0 1
1 2
output
-1
Note
The tree corresponding to samples 1 and 2 are:
In sample 1, we can choose node 1 and k=4 for a cost of 4⋅1 = 4 and select nodes 1,2,3,5, shuffle their digits and get the desired digits in every node.
In sample 2, we can choose node 1 and k=2 for a cost of 10000⋅2, select nodes 1,5 and exchange their digits, and similarly, choose node 2 and k=2 for a cost of 2000⋅2, select nodes 2,3 and exchange their digits to get the desired digits in every node.
In sample 3, it is impossible to get the desired digits, because there is no node with digit 1 initially.
这道题明确一点:节点祖先不影响节点的操作。
换句话说,我们可以通过这样的调整:a[i] = min(a[i], a[fa[i]]);
接下来,不断递归即可。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 200000 + 5;
vector <int> G[maxn];
int n, a[maxn], b[maxn], c[maxn];
long long ans = 0;
void dfs(int u, int Fa)
{
a[u] = min(a[u], a[Fa]);
int size1 = 0, size2 = 0;
for(int i = 0; i < G[u].size(); ++ i)
{
int v = G[u][i];
if(v != Fa)
{
dfs(v, u);
if(b[v] < 0) size2 -= b[v];
else size1 += b[v];
}
}
if(b[u] > 0) ++ size1;
if(b[u] < 0) ++ size2;
b[u] = size1 - size2;
ans += (long long) min(size1, size2) * a[u] << 1ll;
return;
}
int main()
{
scanf("%d", &n);
a[0] = 1 << 30;
for(int i = 0; i <= n; ++ i) G[i].clear();
int x1 = 0, x2 = 0;
for(int i = 1; i <= n; ++ i)
{
scanf("%d %d %d", &a[i], &b[i], &c[i]);
x1 += b[i], x2 += c[i];
b[i] -= c[i];
}
if(x1 != x2) puts("-1");
else
{
int u, v;
for(int i = 1; i < n; ++ i)
{
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0);
printf("%lld
", ans);
}
return 0;
}