VP AtCoder Beginner Contest 381

A - 11/22 String

题意:定义11/22串是前面都是1后面都是21,2的个数相同,中间是一个'/'。 判断给你的字符串是不是11/22串。

模拟即可。

点击查看代码
void solve() {
	int n;
	std::cin >> n;
    std::string s;
    std::cin >> s;
    if (n % 2 == 0 || s.substr(0, n / 2) != std::string(n / 2, '1') || s.substr(n / 2 + 1) != std::string(n / 2, '2') || s[n / 2] != '/') {
    	std::cout << "No\n";
    } else {
    	std::cout << "Yes\n";
    }
}

B - 1122 String

题意:定义1122串为每个奇数位置i,都有ai=ai+1,并且每个数只能恰好出现两次。判断是不是1122串。

一样模拟。

点击查看代码
void solve() {
    std::string s;
    std::cin >> s;
    int n = s.size();
    if (n & 1) {
    	std::cout << "No\n";
    	return;
    }

    std::vector<int> cnt(26);
    for (int i = 0; i < n; i += 2) {
    	if (s[i] != s[i + 1]) {
    		std::cout << "No\n";
    		return;
    	}

    	if (cnt[s[i] - 'a']) {
    		std::cout << "No\n";
    		return;
    	}

    	cnt[s[i] - 'a'] = 1;
    }

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

C - 11/22 Substring

题意:和A题一样,不过要你判断字符串是11/22串的最长子串的长度。

在每个'/'处两边扩展记录最长长度即可。

点击查看代码
void solve() {
	int n;
	std::cin >> n;
	std::string s;
	std::cin >> s;
	int ans = 0;
	for (int i = 0; i < n; ++ i) {
		if (s[i] == '/') {
			int k = 1;
			while (i - k >= 0 && i + k < n && s[i - k] == '1' && s[i + k] == '2') {
				++ k;
			}

			ans = std::max(ans, (k - 1) * 2 + 1);
		}
	}

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

D - 1122 Substring

题意:和B题一样,不过要你判断字符串是1122串的最长子串的长度。

记录每个数出现的次数,分奇数起点和偶数起点分别双指针模拟即可。

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

    std::vector<int> st(n + 1);
    int ans = 0;
    for (int i = 0, j = 0; i + 1 < n;) {
    	j = std::max(i, j);
    	while (j + 1 < n && a[j] == a[j + 1] && st[a[j]] == 0) {
    		st[a[j]] = 1;
    		j += 2;
    	}

    	ans = std::max(ans, j - i);
		st[a[i]] = 0;
    	i += 2;
    }

    for (int i = 1, j = 1; i + 1 < n;) {
    	j = std::max(i, j);
    	while (j + 1 < n && a[j] == a[j + 1] && st[a[j]] == 0) {
    		st[a[j]] = 1;
    		j += 2;
    	}

    	ans = std::max(ans, j - i);
		st[a[i]] = 0;
    	i += 2;
    }

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

E - 11/22 Subsequence

题意:和A一样,不过有Q次询问,每次问你[L,R]区间内11/22最长子序列是多少。

把所有'/'的位置存下来,然后记录12的前缀和。那么每次找到第一个位置大于等于L的'/'和最后一个小于等于R的'/',那么可以二分,如果当前'/'两边1的个数大于等于2的个数我们就应该往左边走,否则往右边走。因为这个二分出来的不一定是最优解,所以我们需要在二分过程中记录答案。

点击查看代码
void solve() {
    int n, q;
	std::cin >> n >> q;
	std::string s;
	std::cin >> s;

	std::vector<int> sum1(n + 1), sum2(n + 1);
	std::vector<int> a;
	for (int i = 0; i < n; ++ i) {
		sum1[i + 1] = sum1[i] + (s[i] == '1');
		sum2[i + 1] = sum2[i] + (s[i] == '2');
		if (s[i] == '/') {
			a.push_back(i + 1);
		}
	}

	while (q -- ) {
		int l, r;
		std::cin >> l >> r;
		int L = std::lower_bound(a.begin(), a.end(), l) - a.begin();
		int R = std::upper_bound(a.begin(), a.end(), r) - a.begin() - 1;
		if (L > R) {
			std::cout << 0 << "\n";
			continue;
		}

		int ans = 0;
		while (L <= R) {
			int mid = L + R >> 1;
			int one = sum1[a[mid]] - sum1[l - 1], two = sum2[r] - sum2[a[mid]];
			ans = std::max(ans, std::min(one, two));
			if (one >= two) {
				R = mid - 1;
			} else {
				L = mid + 1;
			}
		}

		std::cout << ans * 2 + 1 << "\n";
	}
}

F - 1122 Subsequence

题意:跟B题一样,不过要你求最长的1122子序列。

注意值域只有20,我们可以状压。记录满足fi这个状态用到的数的最后位置。用sufi,j记录第i个位置后面j出现的最早位置。那么如果suffi,jsufsuffi,j,j都存在,那么fi可以转移到fi|(1<<j)

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

    for (int i = n - 1; i >= 0; -- i) {
    	suf[i] = suf[i + 1];
    	suf[i][a[i]] = i + 1;
    }

    std::vector<int> f(1 << 20, n + 1);
    f[0] = 0;
    for (int i = 0; i < 1 << 20; ++ i) {
    	if (f[i] > n) {
    		continue;
    	}
    	for (int j = 0; j < 20; ++ j) {
    		if ((~i >> j & 1) && suf[f[i]][j] != 0 && suf[suf[f[i]][j]][j] != 0) {
    			f[i | (1 << j)] = std::min(f[i | (1 << j)], suf[suf[f[i]][j]][j]);
    		}
    	}
    }

    int ans = 0;
    for (int i = 0; i < 1 << 20; ++ i) {
    	if (f[i] <= n) {
    		ans = std::max(ans, __builtin_popcount(i));
    	}
    }

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