Codeforces Round 1002 (Div. 2)


A. Milya and Two Arrays

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

统计ab的种类数cnt1,cnt2,因为长度为n且每个种类的数至少出现两次,所以a中每个数贡献的种类数就是min(cnt2),只要cnt1cnt2>=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\n";
    } else {
    	std::cout << "NO\n";
    }
}

B. Cost of the Array time limit per test1 second

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

我们让所有的k1份都只占一个位置,第二份占多个位置,看能不能不让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 << "\n";
    			return;
    		}
    	}

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

    	std::cout << 2 << "\n";
    }
}

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 << "\n";
    		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});
    	}
    }
}

D. Graph and Graph

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

显然我们让两个图都到一个相同的点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 << "\n";
}
posted @   maburb  阅读(300)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示