#include <bits/stdc++.h>
using namespace std;
int a[2000007];
int cut[2000007];
int tree[2097152]; // drzewo punkt-przedział na wartościach
void insert(int i, int w) {
// cerr << "wpisuje " << i << " " << w << "\n";
tree[i] = w;
i /= 2;
while (i > 0) {
tree[i] = max(tree[2 * i], tree[2 * i + 1]);
i /= 2;
}
}
int read(int i, int first, int last, int left, int right) {
if (first > right || last < left) {
// cerr << first << " " << last << " out of bounds " << left << " " << right << "\n";
return -1;
}
if (first >= left && last <= right) {
// cerr << "czytam " << i << " " << tree[i] << "\n";
return tree[i];
}
return max(read(2 * i, first, (first + last) / 2, left, right),
read(2 * i + 1, (first + last) / 2 + 1, last, left, right));
}
struct adapter {
bool operator()(const pair<int, int> &x, const pair<int, int> &y) {
if (x.first > y.first) {
return true;
} else {
return false;
}
}
};
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
int maxa = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
maxa = max(a[i], maxa);
a[n + i] = a[i];
}
int m = 1;
while (m < maxa) {
m *= 2;
}
// cerr << "maxa = " << maxa << " m = " << m << "\n";
for (int i = 1; i < 2 * m; i++) {
tree[i] = -1;
}
for (int i = 0; i < 2 * n; i++) {
// cerr << "tab[" << i << "] = " << tab[i] << "\n";
// cerr << "CZYTAJ " << tab[i] + m - 1 << " " << maxa + m - 1 << "\n";
cut[i] = read(1, m, 2 * m - 1, a[i] + m - 1, maxa + m - 1);
insert(a[i] + m - 1, i);
// cerr << cut[i] << " ";
}
// cerr << "\n";
// set<pair<int, int>> mniejsze;
int mniejsze = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, adapter> wieksze; // kolejka priorytetowa sortuje od najmniejszych
for (int i = 0; i < n; i++) {
if (cut[i] < 0) {
mniejsze++;
// mniejsze.insert({cut[i], i});
} else {
wieksze.push({cut[i], i});
}
}
// int wyn = mniejsze.size();
int wyn = mniejsze;
// cerr << "mniejsze od 0: ";
// for (auto& [x, y] : mniejsze) cerr << "cut[" << y << "] = " << x << ", ";
// cerr << "\n";
for (int i = 1; i < n; i++) { // teraz i - nowy początek
if (cut[i - 1] < i - 1) {
mniejsze--;
}
else {
// zostaje w większych
}
// przerzucam
while (!wieksze.empty() && wieksze.top().first < i) {
if (wieksze.top().second >= i) {
mniejsze++;
}
wieksze.pop();
}
if (cut[i + n - 1] < i) {
// cerr << "cut[" << i + n - 1 << "] = " << cut[i + n - 1] << " < " << i << "\n";
// mniejsze.insert({cut[i + n - 1], i + n - 1});
mniejsze++;
} else {
// cerr << "cut[" << i + n - 1 << "] = " << cut[i + n - 1] << " >= " << i << "\n";
wieksze.push({cut[i + n - 1], i + n - 1});
}
// cerr << "mniejsze od " << i << ": ";
// for (auto& [x, y] : mniejsze) cerr << "cut[" << y << "] = " << x << ", ";
// cerr << "\n";
// wyn = max(wyn, (int)(mniejsze.size()));
wyn = max(wyn, mniejsze);
}
cout << wyn << "\n";
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #include <bits/stdc++.h> using namespace std; int a[2000007]; int cut[2000007]; int tree[2097152]; // drzewo punkt-przedział na wartościach void insert(int i, int w) { // cerr << "wpisuje " << i << " " << w << "\n"; tree[i] = w; i /= 2; while (i > 0) { tree[i] = max(tree[2 * i], tree[2 * i + 1]); i /= 2; } } int read(int i, int first, int last, int left, int right) { if (first > right || last < left) { // cerr << first << " " << last << " out of bounds " << left << " " << right << "\n"; return -1; } if (first >= left && last <= right) { // cerr << "czytam " << i << " " << tree[i] << "\n"; return tree[i]; } return max(read(2 * i, first, (first + last) / 2, left, right), read(2 * i + 1, (first + last) / 2 + 1, last, left, right)); } struct adapter { bool operator()(const pair<int, int> &x, const pair<int, int> &y) { if (x.first > y.first) { return true; } else { return false; } } }; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; int maxa = 0; for (int i = 0; i < n; i++) { cin >> a[i]; maxa = max(a[i], maxa); a[n + i] = a[i]; } int m = 1; while (m < maxa) { m *= 2; } // cerr << "maxa = " << maxa << " m = " << m << "\n"; for (int i = 1; i < 2 * m; i++) { tree[i] = -1; } for (int i = 0; i < 2 * n; i++) { // cerr << "tab[" << i << "] = " << tab[i] << "\n"; // cerr << "CZYTAJ " << tab[i] + m - 1 << " " << maxa + m - 1 << "\n"; cut[i] = read(1, m, 2 * m - 1, a[i] + m - 1, maxa + m - 1); insert(a[i] + m - 1, i); // cerr << cut[i] << " "; } // cerr << "\n"; // set<pair<int, int>> mniejsze; int mniejsze = 0; priority_queue<pair<int, int>, vector<pair<int, int>>, adapter> wieksze; // kolejka priorytetowa sortuje od najmniejszych for (int i = 0; i < n; i++) { if (cut[i] < 0) { mniejsze++; // mniejsze.insert({cut[i], i}); } else { wieksze.push({cut[i], i}); } } // int wyn = mniejsze.size(); int wyn = mniejsze; // cerr << "mniejsze od 0: "; // for (auto& [x, y] : mniejsze) cerr << "cut[" << y << "] = " << x << ", "; // cerr << "\n"; for (int i = 1; i < n; i++) { // teraz i - nowy początek if (cut[i - 1] < i - 1) { mniejsze--; } else { // zostaje w większych } // przerzucam while (!wieksze.empty() && wieksze.top().first < i) { if (wieksze.top().second >= i) { mniejsze++; } wieksze.pop(); } if (cut[i + n - 1] < i) { // cerr << "cut[" << i + n - 1 << "] = " << cut[i + n - 1] << " < " << i << "\n"; // mniejsze.insert({cut[i + n - 1], i + n - 1}); mniejsze++; } else { // cerr << "cut[" << i + n - 1 << "] = " << cut[i + n - 1] << " >= " << i << "\n"; wieksze.push({cut[i + n - 1], i + n - 1}); } // cerr << "mniejsze od " << i << ": "; // for (auto& [x, y] : mniejsze) cerr << "cut[" << y << "] = " << x << ", "; // cerr << "\n"; // wyn = max(wyn, (int)(mniejsze.size())); wyn = max(wyn, mniejsze); } cout << wyn << "\n"; } |
English