这次CF有事没打,后期补了ABCE
传送门
总思路: 循环找出奇数个奇数,判断是否存在符合的情况
for (int i = 1; i <= x; i += 2){
if (a >= i && b >= x - i){
puts("YES");
f = 1;
break;
}
}
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n, x, y;
int a = 0, b = 0;
scanf("%d%d",&n,&x);
for (int i = 0; i < n; i++){
scanf("%d",&y);
if (y % 2 == 1){
a ++;
}
else{
b ++;
}
}
int f = 0;
for (int i = 1; i <= x; i += 2){
if (a >= i && b >= x - i){
puts("YES");
f = 1;
break;
}
}
if (!f) puts("NO");
}
return 0;
}
总思路 : 利用前缀和记录没点前面有多少 0 ,后面有多少0,然后排着遍历输出最小的费用 (可以用多少个0推出有多少个1)
for (int i = 1; i <= n; i ++){
if (st[i] == '0'){
ans[i] = ans[i - 1] + 1;
}
else{
ans[i] = ans[i - 1];
}
}
for (int i = n; i >= 1; i --){
if (st[i] == '0'){
res[i - 1] = res[i] + 1;
}
else{
res[i - 1] = res[i];
}
}
int num = min(ans[n], n - ans[n]);
for(int i = 1; i <= n; i++){
int x = ans[i] + (n - i - res[i]);
int y = i - ans[i] + res[i];
num = min({x,y,num});
}
#include
#include
#include
#include
#include
using namespace std;
int ans[1010],res[1010];
char st[1010];
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%s",st + 1);
int n = strlen(st + 1);
memset(ans,0,sizeof ans);
memset(res,0,sizeof res);
for (int i = 1; i <= n; i ++){
if (st[i] == '0'){ // 有多少 0
ans[i] = ans[i - 1] + 1;
}
else{
ans[i] = ans[i - 1];
}
}
for (int i = n; i >= 1; i --){
if (st[i] == '0'){
res[i - 1] = res[i] + 1;
}
else{
res[i - 1] = res[i];
}
}
// printf("%d\n",n);
int num = min(ans[n], n - ans[n]);
for(int i = 1; i <= n; i++){
int x = ans[i] + (n - i - res[i]);
int y = i - ans[i] + res[i];
num = min({x,y,num});
}
printf("%d\n",num);
}
return 0;
}
主要思路: 思维博弈,无根树将x点提取为根,然后找谁能先删除即可,最后肯定是剩了2个点,谁能先下手谁就赢。
#include
#include
#include
#include
using namespace std;
int d[1010];
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(d,0,sizeof d);
int n, x;
scanf("%d%d",&n,&x);
for (int i = 1; i <= n - 1; i++){
int u, v;
scanf("%d%d",&u,&v);
d[u]++,d[v]++;
}
if (n == 1 || d[x] == 1){
puts("Ayush");
continue;
}
if (n % 2 == 0){
puts("Ayush");
}
else{
puts("Ashish");
}
}
return 0;
}
主要思路,贪心 + dfs,不太好理解,每条子树的变换点都会取用这条树上的最小值点去变换,dfs记录 0 1 的个数,然后从低向上去贪心计算
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 200010, M = 400010;
int h[N], ne[M], e[M], a[N], b[N], c[N], idx;
int cnt[N][2];
ll ans;
void add(int x, int y){
e[idx] = y, ne[idx] = h[x], h[x] = idx++;
}
void dfs(int u, int fa){
if (fa) a[u] = min(a[u],a[fa]);
int f = -1;
if (b[u] == 0 && c[u]) f = 0;
if (b[u] && c[u] == 0) f = 1;
int c0 = 0, c1 = 0;
for (int i = h[u] ; i != -1; i = ne[i]){
int j = e[i];
if (j != fa){
dfs(j,u);
cnt[u][0] += cnt[j][0];
cnt[u][1] += cnt[j][1];
if (cnt[j][0] > cnt[j][1]) c0 += cnt[j][0] - cnt[j][1];
else c1 += cnt[j][1] - cnt[j][0];
}
}
if (f == 0) cnt[u][0] ++, c0 ++;
if (f == 1) cnt[u][1] ++, c1 ++;
ans += 2ll * a[u] * min(c0,c1);
}
int main(){
memset(h,-1,sizeof h);
int n;
scanf("%d",&n);
for (int i = 1; i <= n; i++){
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
for (int i = 1; i < n ; i++){
int x, y;
scanf("%d%d",&x,&y);
add(x, y), add(y, x);
}
dfs(1,0);
if (cnt[1][0] != cnt[1][1]) ans = -1;
printf("%lld\n",ans);
return 0;
}