santisify Site

Back

Codeforces Round 1002 (Div.2)Blur image

A. Milya and Two Arrays#

A. Milya and Two Arrays

题目描述#

给你两个长度为n的数组a和b,a,b中的每个元素都至少出现两次。你可以重新排列a,最后要使得ai+bi的不同种类大于等于3。

解题思路#

统计a和b的种类数cnt1,cnt2,因为长度为n且每个种类的数至少出现两次,所以a中每个数贡献的种类数就是出现次数,出现次数,min( 出现次数,cnt2),只要cnt1∗cnt2>=3就行。赛时没想的很清楚写的cnt1+cnt2>=4,其实一样。

参考代码#

void solve() {
  int n;
  std::cin >> n;
  std::set<int> a, b;
  for (int i = 0; i < n; ++ i) {
  	int x;
  	std::cin >> x;
  	a.insert(x);
  }

  for (int i = 0; i < n; ++ i) {
  	int x;
  	std::cin >> x;
  	b.insert(x);
  }

  if (a.size() + b.size() >= 4) {
  	std::cout << "YES" << endl;
  } else {
  	std::cout << "NO" << endl;
  }
}
cpp

B. Cost of the Array time limit per test1 second#

B. Cost of the Array time limit per test1 second

题目描述#

给你一个长度为n数组a和一个偶数k。你要把a分成k份。然后把所有偶数份按顺序拼到一起,得到b,求可以得到的bi!=i的最小的i。

解题思路#

我们让所有的k−1份都只占一个位置,第二份占多个位置,看能不能不让1开头,如果有我们可以把前面的1都给第一份,那么答案就是1。否则就全部都是1,那么全部给第二个份,那么答案就是2。
注意要特判n==k的情况

参考代码#

void solve() {
  int n, k;
  std::cin >> n >> k;
  std::vector<int> a(n);
  for (int i = 0; i < n; ++ i) {
  	std::cin >> a[i];
  }

  if (n == k) {
  	for (int i = 1, j = 1; i < n; i += 2, j ++ ) {
  		if (a[i] != j) {
  			std::cout << j << endl;
  			return;
  		}
  	}

  	std::cout << k / 2 + 1 << endl;
  	return;
  } else {
  	for (int i = 1; i < n - (k - 2); ++ i) {
  		if (a[i] != 1) {
  			std::cout << 1 << endl;
  			return;
  		}
  	}

  	std::cout << 2 << endl;
  }
}
cpp

C. Customer Service#

C. Customer Service

题目描述#

给你n个长度为n的数组,你要给每一个数组截断一次,且所有数组截断的位置凑起来正好是一个排列。然后每个数组的值就是截断的后一部分的和。你要让所有数组和的mex最大。

解题思路#

记录每个数组的后缀和与后缀长度相等的位置,那么保留这一段位置可以得到一个数字。于是我们从小到大枚举mex只要有一个没有被操作过的数组可以贡献这个值,就可以继续操作,否则就是答案。然后考虑每个值由哪个数组贡献,应该让可以贡献的最大值最小的数组来贡献这个值。因为其他数组都可以贡献更大的值,应该留下来。

参考代码#

void solve() {
  int n;
  std::cin >> n;
  std::vector a(n, std::vector<int>(n));
  for (int i = 0; i < n; ++ i) {
  	for (int j = 0; j < n; ++ j) {
  		std::cin >> a[i][j];
  	}
  	a[i].push_back(0);
  	std::reverse(a[i].begin(), a[i].end());
  }

  std::vector<std::set<std::pair<int, int> > > s(n + 1);
  std::vector<int> b(n);
  for (int i = 0; i < n; ++ i) {
  	i64 t = 0;
  	for (int j = 0; j <= n; ++ j) {
  		t += a[i][j];
  		if (j == n || t != j) {
  			b[i] = j;
  			break;
  		}
  	}

  	for (int j = 0; j < b[i]; ++ j) {
  		s[j].insert({b[i], i});
  	}
  }

  for (int i = 0; i <= n; ++ i) {
  	if (s[i].empty()) {
  		std::cout << i << endl;
  		return;
  	}

  	auto [_, x] = *s[i].begin();
  	s[i].erase(s[i].begin());
  	for (int j = 0; j < b[x]; ++ j) {
  		s[j].erase({b[x], x});
  	}
  }
}
cpp

D. Graph and Graph#

D. Graph and Graph

题目描述#

给你两个由n个顶点的图,你在图一和图二各有一个起点,你每次要在这两个图上移动,假设从图一移动到了u, 图二移动到了v,移动代价是|u−v|。你要进行无限次操作,求操作的最小代价。

解题思路#

显然我们让两个图都到一个相同的点u,使得有一个v在图一和图二上都和u有边。那么可以在这两个点上反复横跳,代价是0。否则代价是正无穷。 那么可以考虑最短路,dist[i][j]表示图一在i,图二在j时的最小代价。最后枚举每个i,看有没有一个j使得在两个图上都有边,然后取最小值即可。

参考代码#

void solve() {
  int n, s1, s2;
  std::cin >> n >> s1 >> s2;
  -- s1, -- s2;
  std::vector g1(n, std::vector<int>(n));
  std::vector g2(n, std::vector<int>(n));
  std::vector<std::vector<int> > adj1(n);
  std::vector<std::vector<int> > adj2(n);
  int m1, m2;
  std::cin >> m1;
  for (int i = 0; i < m1; ++ i) {
  	int u, v;
  	std::cin >> u >> v;
  	-- u, -- v;
  	g1[u][v] = g1[v][u] = 1;
  	adj1[u].push_back(v);
  	adj1[v].push_back(u);
  }

  std::cin >> m2;
  for (int i = 0; i < m2; ++ i) {
  	int u, v;
  	std::cin >> u >> v;
  	-- u, -- v;
  	g2[u][v] = g2[v][u] = 1;
  	adj2[u].push_back(v);
  	adj2[v].push_back(u);
  }

  const int inf = 1e9;
  std::vector dist(n, std::vector<int>(n, inf));
  std::vector vis(n, std::vector<int>(n));
  using A = std::array<int, 3>;
  std::priority_queue<A, std::vector<A>, std::greater<A> > heap;
  dist[s1][s2] = 0;
  heap.push({0, s1, s2});
  while (heap.size()) {
  	auto [_, x, y] = heap.top(); heap.pop();
  	if (vis[x][y]) {
  		continue;
  	}

  	for (auto & i : adj1[x]) {
  		for (auto & j : adj2[y]) {
  			if (dist[i][j] > dist[x][y] + std::abs(i - j)) {
  				dist[i][j] = dist[x][y] + std::abs(i - j);
  				if (!vis[i][j]) {
  					heap.push({dist[i][j], i, j});
  				}
  			}
  		}
  	}
  }	

  int ans = inf;
  for (int i = 0; i < n; ++ i) {
  	for (int j = 0; j < n; ++ j) {
  	  if (g1[i][j] && g2[i][j]) {
  		  ans = std::min(ans, dist[i][i]);
  		}
  	}
  }

  if (ans == inf) {
  	ans = -1;
  }
  std::cout << ans << endl;
}
cpp
Codeforces Round 1002 (Div.2)
https://santisify.top/blog/old/cf2059
Author santisify
Published at February 7, 2025
Comment seems to stuck. Try to refresh?✨