A. Jagged Swaps
题意:给你一个排列,你每次可以选择一个\(i\), 满足\(a_i > a_{i-1}\) 和 \(a_i > a_{i+1}\),然后交换\(a_i\)和\(a_{i+1}\)。 问能不能给数组升序排列。
显然第一个不能动,所以它一定得是\(1\)。在满足这条件后,我们假设\([1, i]\)已经是升序(不一定是最小的\(i\)个数在里面),那么对于第\(i+1\)个数,如果它大于\(a_i\)我们可以把它接在后面,否则我们让他一直往前移,就类似与冒泡排序,这样我们就对\([1, i + 1]\)进行了排序,于是可得最终可以对\([1, n]\)进行排序。所以如果\(a_1\)等于\(1\),那么YES,否则NO。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}if (a[0] == 1) {std::cout << "YES\n";} else {std::cout << "NO\n";}
}
B. AB Flipping
题意:给你一个只包含\(AB\)的字符串,你每次可以选择一个\(i\), 满足\(s_i = A, s_{i+1} = B\), 然后交换这两个位置上字符,每个位置只能执行一次交换操作,问最多交换多少次。
最前面的\(A\)和最后面的\(B\)之间的位置都可以执行操作,因为对于第\(i\)个位置,如果他不能操作,那么可以把他后面的\(B\)交换下来,和他操作。
点击查看代码
void solve() {int n;std::cin >> n;std::string s;std::cin >> s;int l = 0, r = n - 1;while (l < n && s[l] == 'B') {++ l;}while (r >= 0 && s[r] == 'A') {-- r;}std::cout << std::max(0, r - l) << "\n";
}
C. Matching Arrays
题意:给你两个数组\(a, b\),你要重新排列\(b\),使得\(\sum_{i=1}^{n} a_i > b_i\)正好是\(x\)。
我们给两个数组排好序,那么应该让\(A\)的\([n - x + 1, n]\)个最大的数和\(B\)的\([1, x]\)个最小的数匹配,如果这样还不能匹配\(x\)个,那么没有答案,因为你这些数不能匹配,换一个其他数来肯定也不能匹配。 那么我们接下来要让剩下的\(n - x\)个位置都不匹配,直接让两个数组剩下的数从小到大匹配就行了,因为如果有一个匹配的话,你拿它和比它小的换,换过去的哪个位置的数一定比它小,拿它换比它大的数,这个数依旧比它这个位置上的数大。
点击查看代码
void solve() {int n, m;std::cin >> n >> m;std::vector<int> a(n), b(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}for (int i = 0; i < n; ++ i) {std::cin >> b[i];}std::sort(b.begin(), b.end());std::vector<std::pair<int, int> > c;for (int i = 0; i < n; ++ i) {c.push_back({a[i], i});}std::sort(c.begin(), c.end());std::vector<int> ans(n);for (int i = n - m, j = 0; i < n; ++ i, ++ j) {ans[c[i].second] = b[j];}for (int i = 0, j = m; i < n - m; ++ i, ++ j) {ans[c[i].second] = b[j];}int cnt = 0;for (int i = 0; i < n; ++ i) {cnt += a[i] > ans[i];}if (cnt != m) {std::cout << "NO\n";return;}std::cout << "YES\n";for (int i = 0; i < n; ++ i) {std::cout << ans[i] << " \n"[i == n - 1];}
}
D. Ones and Twos
题意:给你一个只包含\(1\)和\(2\)的数组,每次会问你有没有一个子数组的和等于\(x\)或着修改一个位置上的数。
应该是这道题变过来的 https://www.luogu.com.cn/problem/P3514
如果有区间的和为\(x\),那么也一定有区间和为\(x-2\),因为假设这个\(x\)这个区间为\([l, r]\),那么如果\(l\)或者\(r\)这个位置是\(2\),显然区间缩小一位和就是\(x-2\),否则两边都是\(1\)那么两边都缩一位一样是\(x-2\)。所以我们只要找最大的奇数和最大的偶数就行。
我们最大的奇数或偶数有一个一定是\(sum_{1n}\),另一个要求最大我们只要从两边减去应该奇数就行,于是我们存所有\(1\)的位置,每次找最左边的\(1\)和最右边的\(1\)比较哪边减去的值小,就可以得到另一个最大的数。
点击查看代码
void solve() {int n, q;std::cin >> n >> q;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}int sum = std::accumulate(a.begin(), a.end(), 0);std::set<int> s;for (int i = 0; i < n; ++ i) {if (a[i] == 1) {s.insert(i);}}while (q -- ) {int op, x, y;std::cin >> op >> x;;if (op == 1) {int max[2] = {};max[sum & 1] = sum;if (s.empty()) {max[~sum & 1] = -1;} else {int l = *s.begin() * 2 + 1, r = (n - 1 - *s.rbegin()) * 2 + 1;max[~sum & 1] = sum - std::min(l, r);}if (max[x & 1] >= x) {std::cout << "YES\n";} else {std::cout << "NO\n";}} else {std::cin >> y;-- x;s.erase(x);sum -= a[x];a[x] = y;sum += a[x];if (a[x] == 1) {s.insert(x);}}}
}
E. Permutation Sorting
题意:给你应该排列,要让所有数都会到下标等于这个数的位置上,每次把不满足条件的数拿出来右移一下,问\(a_i\)什么时候等于\(i\)。
每个数要去的地方是固定的,我们可以找出来,设\(x\)在\(i\),它的目标是\(j\),那么如果有其他数在\([i, j]\)之间出发,并且目的地也在\([i, j]\)之间,那么\(x\)就可以少移动一位,因为这个数不会堵到他前面了,本来是一位一位移,现在前面少了一位,就可以少走一步。
因为它是应该环,所有我们破环成链,把这个移动序列延长两倍,然后求出每个数的起点和终点,那么就变成对于每个\([x_i, y_i]\),有多少\(x_j > x_i\)并且\(y_j < y_i\)的,我们按\(x\)排序,从大到小做,用树状数组维护\(y\)的前缀和就行。
点击查看代码
struct Fenwick {int n;std::vector<int> tr;Fenwick(int _n) : n(_n) {tr.assign(_n + 1, 0);}void modify(int x, int v) {for (int i = x; i <= n; i += i & -i) {tr[i] += v;}}int query(int x) {int res = 0;for (int i = x; i ; i -= i & -i) {res += tr[i];}return res;}int sum(int l, int r) {return query(r) - query(l - 1);}
};void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];-- a[i];}std::vector<int> ans(n, 1e9);std::vector<std::pair<int, int> > b, c;for (int i = 0; i < n; ++ i) {if (a[i] == i) {ans[i] = 0;} else {b.push_back({a[i], i});}}int m = b.size();for (int i = 0; i < m; ++ i) {b.push_back(b[i]);}std::vector<int> val(2 * m + 1), suf(n, 1e9);std::vector<std::array<int, 3> > Q;for (int i = 2 * m - 1; i >= 0; -- i) {if (suf[b[i].first] != 1e9) {val[i + 1] = suf[b[i].first] - i;Q.push_back({i + 1, suf[b[i].first] + 1, b[i].first});}suf[b[i].second] = i;}std::sort(Q.begin(), Q.end(), std::greater<std::array<int, 3> >());Fenwick tr(2 * m);for (auto & [l, r, id] : Q) {ans[id] = r - l - tr.query(r);tr.modify(r, 1);}for (int i = 0; i < n; ++ i) {std::cout << ans[i] << " \n"[i == n - 1];}
}