F. Strange Array(Codeforces Round #727 (Div. 2))(主席树)
F. Strange Array
給定一個長度為nnn的數組aaa,1≤ai≤n1 \leq a_i \leq n1≤ai?≤n,對于每個aia_iai?,我們要找到一個l≤i,r≥il \leq i, r \geq il≤i,r≥i,
使得,我們對區間[l,r][l, r][l,r]升序后,值為aia_iai?的數與中位數相隔最遠,輸出這個最遠距離。
我們分兩種情況討論:
-
aia_iai?在中位數的左邊,也就是ai≤a_i \leqai?≤中位數,我們考慮把aj≥aia_j \geq a_iaj?≥ai?的設置為111,其他都設置為?1-1?1,
則我們就是要對每個iii找到一個區間[l,r][l, r][l,r],使得區間和最大,假設這個區間和為xxx,則答案即為x2\frac{x}{2}2x?
-
aia_iai?在中位數的右邊,也就是ai≥a_i \geqai?≥中位數,我們考慮把aj≤aia_j \leq a_iaj?≤ai?的設置為111,其他設置為?1-1?1,
則我們就是要對每個iii找到一個區間[l,r][l, r][l,r],使得區間和最大,假設這個區間和為xxx,則答案即為x+12?1\frac{x + 1}{2} - 12x+1??1。
綜上我們對這兩個答案取maxmaxmax即可,至于對值的維護,我們可以考慮用主席樹維護區間左、右最大和即可。
#include <bits/stdc++.h>using namespace std;const int N =2e5 + 10;int root[N], ls[N << 5], rs[N << 5], num;int a[N], ans[N], n;vector<int> P[N];struct Res {int lsum, sum, rsum; }T[N << 5];Res operator + (Res a, Res b) {return {max(a.lsum, a.sum + b.lsum), a.sum + b.sum, max(a.rsum + b.sum, b.rsum)}; }void push_up(int rt) {T[rt] = T[ls[rt]] + T[rs[rt]]; }void build(int &rt, int l, int r) {rt = ++num;if (l == r) {T[rt] = {1, 1, 1};return ;}int mid = l + r >> 1;build(ls[rt], l, mid);build(rs[rt], mid + 1, r);push_up(rt); }void update(int &rt, int pre, int l, int r, int x, int v) {rt = ++num, ls[rt] = ls[pre], rs[rt] = rs[pre];if (l == r) {T[rt] = {v, v, v};return ;}int mid = l + r >> 1;if (x <= mid) {update(ls[rt], ls[pre], l, mid, x, v);}else {update(rs[rt], rs[pre], mid + 1, r, x, v);}push_up(rt); }Res query(int rt, int l, int r, int L, int R) {if (l >= L && r <= R) {return T[rt];}int mid = l + r >> 1;if (L <= mid && R > mid) {return query(ls[rt], l, mid, L, R) + query(rs[rt], mid + 1, r, L, R);}else if (L <= mid) {return query(ls[rt], l, mid, L, R);}else {return query(rs[rt], mid + 1, r, L, R);} }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);P[a[i]].push_back(i);}build(root[1], 1, n);for (int i = 2; i <= n; i++) {root[i] = root[i - 1];for (auto it : P[i - 1]) {update(root[i], root[i], 1, n, it, -1);}}for (int i = 1; i <= n; i++) {int lsum = 0, rsum = 0, sum = 1;if (i != 1) {lsum = query(root[a[i]], 1, n, 1, i - 1).rsum;}if (i != n) {rsum = query(root[a[i]], 1, n, i + 1, n).lsum;}if (lsum > 0) {sum += lsum;}if (rsum > 0) {sum += rsum;}ans[i] = max(ans[i], sum >> 1);}for (int i = 1; i <= num; i++) {ls[i] = rs[i] = 0;}for (int i = 1; i <= n; i++) {root[i] = 0;}num = 0;build(root[n], 1, n);for (int i = n - 1; i >= 1; i--) {root[i] = root[i + 1];for (auto it : P[i + 1]) {update(root[i], root[i], 1, n, it, -1);}}for (int i = 1; i <= n; i++) {int lsum = 0, rsum = 0, sum = 1;if (i != 1) {lsum = query(root[a[i]], 1, n, 1, i - 1).rsum;}if (i != n) {rsum = query(root[a[i]], 1, n, i + 1, n).lsum;}if (lsum > 0) {sum += lsum;}if (rsum > 0) {sum += rsum;}ans[i] = max(ans[i], (sum + 1) / 2 - 1);}for (int i = 1; i <= n; i++) {printf("%d%c", ans[i], i == n ? '\n' : ' ');}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的F. Strange Array(Codeforces Round #727 (Div. 2))(主席树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C - Swaps 2(树状数组,思维)
- 下一篇: 哺乳期可以游泳吗