首页 > 其他分享 >P3514 [POI2011] LIZ-Lollipop

P3514 [POI2011] LIZ-Lollipop

时间:2025-01-15 22:44:05浏览次数:1  
标签:std int sum POI2011 LIZ 区间 P3514

题意:给你一个字符串,'T'代表2, 'W'代表1。\(m\)次询问,每次问你有没有一个区间和等于\(x\),有则输出一个区间,否则输出"NIE"。

我们观察只给1和2这两个值有什么用,如果我们知道\(x\)是有的,并且区间为\(l_x\) 和 \(r_x\),那么如果\(s[l_x]\) 或者 \(s[r_x]\)为2,是不是能推出\(x-2\),否则两边都是1,也能推出\(x-2\),所有如果\(x\)存在,那么小于\(x\)的且和\(x\)奇偶性相同的数也存在。
那么我们找到最大的奇数和偶数就行了,先求\(sum_n\),得到一个最大的数,然后左右找一个奇数区间,减去后就得到另一个最大的数。然后从大到小循环确定方案就行了。

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

	std::vector<int> sum(n + 1);
	for (int i = 0; i < n; ++ i) {
		sum[i + 1] = sum[i] + (s[i] == 'T' ? 2 : 1);
	}

	std::vector<int> l(2 * n + 1, n + 1), r(2 * n + 1);
	l[sum[n]] = 1; r[sum[n]] = n;
	for (int i = 1; i <= n; ++ i) {
		if (sum[i] & 1) {
			l[sum[n] - sum[i]] = i + 1;
			r[sum[n] - sum[i]] = n;
			break;
		}
	}

	for (int i = n; i >= 1; -- i) {
		if ((sum[n] - sum[i - 1]) & 1) {
			l[sum[i - 1]] = 1;
			r[sum[i - 1]] = i - 1;
		}
	}

	for (int i = 2 * n; i >= 2; -- i) {
		if (l[i] <= r[i]) {
			if (s[l[i] - 1] == 'T') {
				l[i - 2] = l[i] + 1;
				r[i - 2] = r[i];
			} else if (s[r[i] - 1] == 'T') {
				l[i - 2] = l[i];
				r[i - 2] = r[i] - 1;
			} else {
				l[i - 2] = l[i] + 1;
				r[i - 2] = r[i] - 1;
			}
		}
	}

	while (m -- ) {
		int x;
		std::cin >> x;
		if (x <= 2 * n && l[x] <= r[x]) {
			std::cout << l[x] << " " << r[x] << "\n";
		} else {
			std::cout << "NIE\n";
		}
	}
}

标签:std,int,sum,POI2011,LIZ,区间,P3514
From: https://www.cnblogs.com/maburb/p/18673846

相关文章