VP Educational Codeforces Round 4


A. The Text Splitting

题意:给你一个字符串,你要把它分成若干个长度为p或者长度为q的字符串。

考虑枚举分成几个长度为p的字符串,剩下长度是q的倍数则合法。

点击查看代码
void solve() {
	int n, a, b;
	std::cin >> n >> a >> b;
	std::string s;
	std::cin >> s;
	for (int i = 0; i <= n / a; ++ i) {
		if ((n - i * a) % b == 0) {
			std::cout << i + (n - i * a) / b << "\n";
			int j = 0;
			for (; j < i * a; j += a) {
				std::cout << s.substr(j, a) << "\n";
			}

			for (; j < n; j += b) {
				std::cout << s.substr(j, b) << "\n";
			}
			return;
		}
	}

	std::cout << -1 << "\n";
}

B. HDD is Outdated Technology

题意:给你一个排列,你要按顺序从1走到n,每次代价是两个位置坐标的差的绝对值,求总代价。

记录每个数出现的位置,然后从小到大记录。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	int x;
    	std::cin >> x;
    	a[x] = i;
    }

    i64 ans = 0;
    for (int i = 2; i <= n; ++ i) {
    	ans += std::abs(a[i] - a[i - 1]);
    }

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

C. Replace To Make Regular Bracket Sequence

题意:有四种左括号和右括号,每种类型的括号匹配形成一个合法的序列,你可以把任意一个括号变成另一个同左右类型的括号,问最少改变几个括号使得序列合法。

每个右括号是和离自己最近的左括号匹配的,那么用栈存每个左括号,遇到一个右括号则判断是不是同一类型的左括号,不是则需要改变一次。

点击查看代码
void solve() {
    std::string s;
    std::cin >> s;
    std::stack<char> stk;
    std::map<char, char> mp;
    mp['}'] = '{';
    mp[']'] = '[';
    mp[')'] = '(';
    mp['>'] = '<';
    int ans = 0;
    for (auto & c : s) {
    	if (c == ')' || c == '}' || c == ']' || c == '>') {
    		if (stk.empty()) {
    			std::cout << "Impossible\n";
    			return;
    		}
    		if (stk.top() != mp[c]) {	
	    		++ ans;
    		}
    		stk.pop();
    	} else {
    		stk.push(c);
    	}
    }

    if (stk.size()) {
    	std::cout << "Impossible\n";
    	return;
    }

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

D. The Union of k-Segments

题意:给你n个区间,求有多少区间至少被k个区间覆盖。

用差分的思想,把一个区间变成两个贡献:(l,1),(r,1),然后从大到小遍历,记录每次值大于等于k的段的最左端点,直到小于k时加入答案即可。

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<std::pair<int, int>> a;
    for (int i = 0; i < n; ++ i) {
    	int l, r;
    	std::cin >> l >> r;
    	a.push_back({l, 1});
    	a.push_back({r + 1, -1});
    }

    std::sort(a.begin(), a.end());
    int sum = 0;
    int last = 2e9;
    std::vector<std::pair<int, int>> ans;
    for (auto & [x, v] : a) {
    	sum += v;
    	if (sum >= k) {
    		last = std::min(last, x);
    	} else {
    		if (last <= x) {
    			ans.push_back({last, x - 1});
    		}
    		last = 2e9;
    	}
    }

    std::cout << ans.size() << "\n";
    for (auto & [l, r] : ans) {
    	std::cout << l << " " << r << "\n";
    }
}

E. Square Root of Permutation

题意:一个排列进行qi=qqi的变化后变成了p,现在给你一个p,求一个合法的q

对于qi,让iqi连边,那么因为每个点正好是一个出度一个入度,所以会形成若干个环。然后模拟方向,这个环到了p里会被打乱,每个位置指向的数是原来它指向的数的指向的数。那么每个环会根据位置的奇偶分成两个环,但发现奇数环的最后一个点会把两个环连接起来,所以如果环的长度是奇数,那么只需要两个两个跳着走还原奇数位置和偶数位置上的数,就可以得到原来的环。如果是长度为偶数的环,它会变成两个长度一样的环,那么可以两两匹配,一个环当成奇数位置的环一个环当成偶数位置的环,就可以用还原原来的环,如果没有匹配的则无解。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> b(n + 1), vis(n + 1);
    std::vector<int> pre(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	if (!vis[i]) {
    		std::vector<int> c;
    		while (!vis[i]) {
    			vis[i] = 1;
    			c.push_back(i);
    			i = a[i];
    		}

    		int m = c.size();
    		if (m & 1) {
    			std::vector<int> d(m);
    			for (int j = 0, k = 0; j < m; k = (k + 2) % m, ++ j) {
    				d[k] = c[j];
    			}

    			for (int j = 0; j < m; ++ j) {
    				b[d[j]] = d[(j + 1) % m];
    			}
    		} else {
    			if (pre[m]) {
    				std::vector<int> d(m * 2);
    				for (int j = 0, x = i, y = pre[m]; j < m * 2; ++ j) {
    					if (j % 2 == 0) {
    						d[j] = x;
    						x = a[x];
    					} else {
    						d[j] = y;
    						y = a[y];
    					}
    				}

    				for (int j = 0; j < m * 2; ++ j) {
    					b[d[j]] = d[(j + 1) % (m * 2)];
    				}

    				pre[m] = 0;
    			} else {
    				pre[m] = i;
    			}
    		}
    	}
    }

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

    for (int i = 1; i <= n; ++ i) {
    	std::cout << b[i] << " \n"[i == n];
    }
}

F. Simba on the Circle

待补

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