Codeforces Global Round 16(A - E)

A. Median Maximization

简单的贪心构造 题意让求中位数最大为多少 已知序列中所有数字均为非负 则我们可以让中位数之前的数全为0 然后中位数则可以最大取到总数除以剩下数向下取整
代码

#include <bits/stdc++.h>
 
using namespace std;
 
int n, s;
 
void solve()
{
	cin >> n >> s;
	if (n % 2 == 1) 
	{
		int m = n - n / 2;
		cout << s / m << endl;
	}
	else
	{
		int m = n - (n / 2 - 1);
		cout << s / m << endl;
	}
}
 
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	
	int T;
	cin >> T;
	
	while (T -- )
	{
		solve();
	}
	
	return 0;
} 

B. MIN-MEX Cut

依旧是贪心 题意为 给定一个字符串可以分为若干小字符串 其中每个字符串的价值为 mex(当前字符串包含的数字) 对于01我们可以取到2 对于0我们可以取到1 对于1我们可以取到0 需要求最小价值和
因此我们可以看看有多少连续的只包含0的子字符串 如果数量大于2我们可以直接取整个字符串 价值为2 如果小于2我们可以取连续0的块数

#include <bits/stdc++.h>
 
using namespace std;
 
const int N = 1e5 + 10;
 
string s;
 
void solve()
{
	cin >> s;
	
	int tot = 0;
	for (int i = 1; i < s.size(); i ++ )
		if (s[i] == '1' && s[i] != s[i - 1]) tot ++ ;
	if (s[s.size() - 1] == '0') tot ++ ;
	if (tot < 2) cout << tot << endl;
	else cout << 2 << endl;
}
 
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	
	int T;
	cin >> T;
	
	while (T -- )
	{
		solve();
	}
	
	return 0;
} 

C - MAX-MEX Cut

和b差不多 给定两行字符串 mex为[l, r]中上下两行所有01的mex 让我们分为若干子字符串求最大的价值和
简单构造题 对于上下均为0(用a0 b0表示)的我们可以选择保留看看后面是否为a1 b1如果是的话我们用这两行可以取到2 如果是a0 b0 我们可以选择ans加上前面a0 b0(价值为1) 然后再看当前行之后是否有a1 b1 如果遇到a0 b1 或者a1 b0可以直接加上2
代码

#include <bits/stdc++.h>
 
using namespace std;
 
const int N = 1e5 + 10;
 
int n;
string a, b;
 
void solve()
{
	cin >> n;
	cin >> a >> b;
	int t1 = -1, t2 = -1; // t1是前一排 t2是后一排
	 
	int ans = 0; 
	for (int i = 0; i < n; i ++ )
	{
		if (a[i] != b[i]) t2 = 2;
		else if (a[i] == '1') t2 = 0;
		else t2 = 1;
		
		
			if (t2 == 2)
			{
				if (t1 != -1) ans += t1;
				ans += t2;
				t1 = t2 = -1;
			}
			else if (t1 != -1 && t1 ^ t2)
			{
				ans += 2;
				t1 = t2 = -1;
			}
			else if (t1 != -1 && t1 == t2)
			{
				if (t1 == 1) ans += t1, t1 = 1;
				t1 = -1;
			}
		t1 = t2;
	}
	if (t1 != -1) ans += t1;
	cout << ans << endl;
}
 
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	
	int T;
	cin >> T;
	
	while (T -- )
	{
		solve();
	}
	
	return 0;
} 

D1. Seating Arrangements (easy version)

阅读理解题 感觉有点脑残
思路很简单直接暴力即可 仅有一行人 每个人都要按视力来排序 排序后前面每有一个序列号小于他的 价值就要加一 求最小价值和
代码

#include <bits/stdc++.h>
 
#define int long long
 
using namespace std;
 
const int N = 1e5 + 10;
 
int n, m;
int a[N];
 
void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i ++ ) cin >> a[i];
	int ans = 0;
	for (int i = 1; i <= m; i ++ )
		for (int j = 1; j < i; j ++ )
			if (a[j] < a[i]) ans ++ ;
	cout << ans << endl;
}
 
signed main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	
	int T;
	cin >> T;
	
	while (T -- )
	{
		solve();
	}
	
	return 0;
} 

D2. Seating Arrangements (hard version)

D1的难度增加版 有n行 每个人经过前面人时ans要++ 排序依然是按照视力来排序 最后对于当前视力大小的序列是一定的 我们为了减小价值和 需要通过一定的排序来优化 对于第i行的最后一人和第i+1行的第一人 假如两人视力相等 则显然当第i行最后一人的排队序号较小时可以使得价值和较小 对于同一排 的第i人和第i+1人 显然当第i人的排队序号较大时可以使得价值和较小
则我们建立两个排序分别对总序列以及每排的序列进行排序求ans
代码

#include <bits/stdc++.h>
 
using namespace std;
 
const int N = 350;
 
int n, m;
struct Node
{
	int value, idx;
}a[N * N];
 
bool cmp1(Node x, Node y)
{
	if (x.value == y.value) return x.idx < y.idx;
	return x.value < y.value;
}
 
bool cmp2(Node x, Node y)
{
	if (x.value == y.value) return x.idx > y.idx;
	return x.value < y.value;
}
 
void solve()
{
	cin >> n >> m;
	
	for (int i = 1; i <= n * m; i ++ ) 
	{
		cin >> a[i].value;
		a[i].idx = i;
	}
	
	sort(a + 1, a + 1 + n * m, cmp1);
	
	int ans = 0;
	for (int i = 1; i <= n; i ++ )
	{
		sort(a + 1 + (i - 1) * m, a + 1 + i * m, cmp2);
		int l = (i - 1) * m + 1, r = i * m;
		for (int j = l; j <= r; j ++ )
			for (int k = l; k < j; k ++ )
				if (a[j].idx > a[k].idx) ans ++ ;
	}
	
	cout << ans << endl;
}
 
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	
	int t;
	cin >> t;
	
	while (t -- )
	{
		solve();
	}
	
	return 0;
} 

E. Buds Re-hanging

题意很好懂 令每个花蕾为子节点只包含叶子结点且子节点个数大于1 然后可以移动花蕾结点至其他叶子结点 问进行若干次移动之后 最小的叶子结点数目为多少
这个题我们可以把所有花蕾以及可以变为花蕾的节点包含它的叶子结点都给分离出来然后随便再组合 每次组合都会使得ans-1 可以从下往上找然后再加起来即为最优解
代码

#include <bits/stdc++.h>
 
using namespace std;
 
const int N = 2e5 + 10, M = N * 2;
 
int n, ans;
int h[N], e[M], ne[M], idx;
 
void init()
{
	memset(h, -1, sizeof h);
	idx = 0, ans = 1;
} 
 
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
 
int dfs(int cur, int fa)
{
	int cnt = 0;
	for (int i = h[cur]; ~i; i = ne[i])
	{
		int j = e[i];
		if (j == fa) continue;
		cnt += dfs(j, cur);
	}
	
	if (cnt) 
	{
		ans += (cnt - 1);
		return 0;
	}
	return 1;
}
 
void solve()
{
	init();
	cin >> n;
	
	for (int i = 1; i < n; i ++ )
	{
		int u, v;
		cin >> u >> v;
		add(u, v), add(v, u);
	}
	
	dfs(1, 0);
	
	cout << ans << endl;
}
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int T;
	cin >> T;
	
	while (T -- )
	{
		solve();
	}
	
	return 0;
}





刚开始写题解 所以有的时候思路表达的不太清晰 强推一下b站电音抖腿不能改 几乎每次都会讲解cf
链接

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值