P10131 [USACO24JAN] Majority Opinion B 题解

大意:

给定你一个长度为 \(n\) 的序列 \(\{h\}\)\(1\le h_i\le n\),你可以对其进行若干次操作,操作为:

  1. 选定一个区间 \([l,r]\)
  2. 若在 \(i\in[l,r]\) 中存在 \(h_i\) 的数量大于 \(\lfloor\frac{l+r}{2}\rfloor\),则令所有的 \(k\in[l,r]\) 上的 \(h_k=h_i\)

求所有可能使 \(\{h\}\) 中的所有元素都变成 \(h_i\)\(h_i\) 个数,并以升序输出可能的 \(h_i\),或判断无解。

分析:

先给出结论,如果存在一个长度为 3 的区间有 2 个及以上的 \(h_i\),那么 \(h_i\) 就是合法的。

考虑证明。

先证明充分性,对于一个长度为 3 的区间,若存在两个及以上的相同元素,则这个区间可以变为相同元素,而我们将该区间变为相同元素后,可以一个一个地扩展左右边界,因为区间长度只加一,而除了新加进来的这个元素,其他元素都是相同的,所以这个元素也会变成相同的,这样就可以保证扩展到整个区间。证毕。

再证明必要性,区间长度小于 3 时是显然的,区间长度大于 3 时,所需要的最少相同元素个数就是 \(\lfloor\frac{l+r}{2}\rfloor+1\)\(r-l+1\) 为奇数时,想要在该区间内获得最长的相同元素个数小于 \(\lfloor\frac{l_1+r_1}{2}\rfloor+1\) 的区间 \([l_1,r_1]\) 就需要隔一个放一个 \(h_i\),但即使如此也才能得到 2,无论向左或向右扩展都是得到一个长度为 3 的区间且相同元素个数大于半区间长。\(r-l+1\) 为偶时也是要隔开放置,然后在此基础上还要在其中隔开来的地方再放一个 \(h_i\),显然得不到长度为 3 及以上。由上可知,所有的区间长度大于 3 的合法区间里面都含有区间长度为 3 的小合法区间。证毕。

Code:

#include <bits/stdc++.h>
#include <bits/extc++.h>
#define ll long long
#define ull unsigned long long
#define m_p make_pair
#define m_t make_tuple
using namespace std;
using namespace __gnu_pbds;
int h[200010];
bitset<200010> v;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	int T, n, x, fl;
	cin >> T;
	while (T--)
	{
		cin >> n;
		fl = 0;
		for (int i = 1; i <= n; i++)
		{
			cin >> x;
			if (h[x] && (h[x] == i - 1 || h[x] == i - 2))
				v[x] = 1;
			h[x] = i;
		}
		for (int i = 1; i <= n; i++)
		{
			if (v[i])
			{
				if(fl)
					cout << " ";
				cout << i;
				fl = 1;
			}
			v[i] = 0;
			h[i] = 0;
		}
		if(!fl)
			cout << "-1";
		cout << "\n";
	}
	return 0;
}

posted @ 2024-02-23 15:47  -wryyy-  阅读(27)  评论(0编辑  收藏  举报