HUST Selection 2025

HUST Selection 2025

这场是真难呵,跟我说这是新生赛???

image-20251025022112724

[J] [2023 ICPC Asia Jinan Regional [I]] Strange Sorting

从A看到I,愣是没做出一个,已耗时四小时。看这个感觉有点想法,懒得证明直接靠感觉猜,没想到一发入魂AC。据说这个是签到题。

Given a sequence \(\vec a\) which is a permutation of \(\mathbb{N}\cap[1,n]\), your task is to sort the permutation in ascending order by applying the following operation for at most \(\left\lfloor\frac{1}{2}n\right\rfloor\) times: Choose two indices \(l\) and \(r\) satisfying \(1\leq l<r\leq n\) and \(a_l>a_r\), and then sort \(a_{[l,r]}\) in ascending order.

Input

There are \(T\) test cases.

\(n\in\mathbb{N}\cap[1,100]\). It is guaranteed that the sum of all test cases will not exceed \(19^4\).

Output

For each test case, first output one line containing one integer \(k\ \left(0\leq k\leq\left\lfloor\frac{1}{2}n\right\rfloor\right)\) indicating the number of operations you're going to use. Then output \(k\) lines, where the \(i\)-th line contains two integers \(l_i\) and \(r_i\) separated by a space, indicating the two indices you choose for the \(i\)-th operation.

It can be proven that the answer always exists. If there are multiple valid answers, you can output any of them.

我的想法是直接每次暴力寻找离得最远的两个逆序对作为要排序区间的两端,然后排序,一直取到没有逆序对为止即得到升序序列。我感觉最坏的情况就是\((2,1,4,3,6,5,8,7,\dots)\)这样的序列,因为这样所有的逆序对的跨度都最小,而跨度越大对我越有利。

一个证明的尝试

姑且只考虑\(n\)是偶数的情形。假设\(\vec{a}=(a_i)_{i=0}^{n-1}\)就是符合我们上述性质的序列,即

\[a_i=2\left(\left\lfloor\frac{i}{2}\right\rfloor+1\right)-i\bmod2= \begin{cases} 2\left\lfloor\frac{i}{2}\right\rfloor+2 & (i\bmod2=0)\\ 2\left\lfloor\frac{i}{2}\right\rfloor+1 & (i\bmod2=0) \end{cases}. \]

对于同一逆序对内的两个数\((a_{2i},a_{2i+1})\),如果将其交换,则总的逆序对数会减少\(1\),我们的策略需要的步数会减少\(1\)

下面来考虑不在同一逆序对内的两个数。任取\(i,j\in\mathbb{N},\ i<j<\frac{1}{2}n\)。根据我们的策略,要将现在的\([2i,2j+1]\)排序,需要进行\(j-i+1\)次操作。考虑以下的几种交换(设交换后的序列为\(\vec{a'}=(a'_i)_{i=0}^{n-1}\))。

  • 如果交换第\(2i\)项与第\(2j\)项:此时有\(a'_{2i}=a_{2j}>a_{2j+1}=a'_{2j+1}\),要排序\([2i,2j+1]\)只需直接选择\([2i,2j+1]\)进行操作即可,操作次数减少为\(1\)
  • 如果交换第\(2i\)项与第\(2j+1\)项:此时有\(a'_{2i}=a_{2j+1}>a_{2i}=a'_{2j+1}\)。同理,此时只需\(1\)次。以上两种情况相同,因为都是制造了新的逆序对。新的逆序对的跨度不可能比原本有的小,而这里制造的都是跨度大于\(1\)的。
  • 如果交换第\(2i+1\)项与第\(2j\)项:此时有\(a'_{2i}=a_{2i}>a_{2i+1}=a'_{2j}\),先将\([2i,2j]\)排序,得到\(\vec{a''}=(a''_i)_{i=0}^{n-1}\);然后因为\(a''_{2j}=a_{2j}>a_{2j+1}=a''_{2j+1}\),再对\([2j,2j+1]\)执行一次操作即可。总的操作次数\(2\leq j-i+1\)
  • 如果交换第\(2i+1\)项与第\(2j+1\)项:此时有\(a'_{2i}=a_{2i}>a_{2i+1}=a'_{2j+1}\),直接对\([2i,2j+1]\)执行操作即可,操作次数减少为\(1\)

由上可知该序列是一个“极小值点”。但我不知道如何证明其就是“最小值点”。

size_t n;
std::vector<int32_t> arr;
std::vector<std::pair<size_t, size_t>> opers;

inline void preprocess() {}

inline std::pair<size_t, size_t> getFarthestInverse() {
	std::pair<size_t, size_t> res{0, 0};
	for (size_t i = 0; i < n; ++i) {
		for (size_t j = i + 1; j < n; ++j) {
			if (arr[i] > arr[j] && j - i > res.second - res.first) {
				res.first = i;
				res.second = j;
			}
		}
	}
	return res;
}

inline void solve() {
	std::cin >> n;
	arr.resize(n);
	opers.clear();
	opers.reserve(n >> 1);
	for (auto &x : arr) std::cin >> x;

	while (!std::is_sorted(arr.begin(), arr.end())) {
		auto farthest = getFarthestInverse();
		opers.emplace_back(farthest);
		std::sort(arr.begin() + farthest.first, arr.begin() + farthest.second + 1);
	}

	std::cout << opers.size() << '\n';
	for (const auto &oper : opers) {
		std::cout << (oper.first + 1) << ' ' << (oper.second + 1) << '\n';
	}
}

时间复杂度:单个测试点最坏为\(O(n^3)\)\(T\)个测试点的最坏总复杂度为\(O\left(\sum_{i=0}^{T-1}n_i^3\right)\)。我也不知道怎么严格证明这个复杂度是可接受的,反正就是AC了。

[B] [2021 ICPC Asia Nanjing Regional] Klee in Solitary Confinement

Given \(n\in\mathbb{N}^*,\ m\in\mathbb{Z}\) and an array \(\vec{a}=(a_i)_{i=0}^{n-1}\). You can perform the following operation at most once: Choose two integers \(b,e\text{ s.t. }0\leq b<e\leq n\) and add \(m\) to every \(a_i\) where \(i\in\mathbb{N}\cap[b,e)\). Compute the maximum occurrence of the mode number of the whole sequence if you choose to perform (or not perform) the operation optimally.

Input

\(n,|m|\leq10^6\).

posted @ 2025-10-25 03:37  我就是蓬蒿人  阅读(5)  评论(0)    收藏  举报