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 130 131 132 133 134
| #include <algorithm> #include <iostream> #include <limits> #include <unordered_map> #include <vector>
using namespace std;
struct SegmentTree { struct Node { int sum = numeric_limits<int>::min(); int prefix = numeric_limits<int>::min(); bool isValid() const { return sum != numeric_limits<int>::min() && prefix != numeric_limits<int>::min(); } Node &operator=(const Node &rhs) { this->sum = rhs.sum; this->prefix = rhs.prefix; return *this; } }; const int MAX_N = 1 << 17;
vector<Node> dat; int n; SegmentTree(int n_, int a[]) { n = 1; while (n < n_) n *= 2;
dat.resize(2 * n); for (int i = 0; i < n_; ++i) { update(i, a[i]); } }
void print() const { for (const auto &d : dat) { cout << "{" << d.sum << ", " << d.prefix << "}, "; } cout << endl; }
void update(int k, int a) { k += n - 1; dat[k].sum = a; dat[k].prefix = a; while (k > 0) { k = (k - 1) / 2; if (!dat[2 * k + 2].isValid()) dat[k] = dat[2 * k + 1]; else { dat[k].sum = dat[2 * k + 1].sum + dat[2 * k + 2].sum; dat[k].prefix = max(dat[2 * k + 1].prefix, dat[2 * k + 1].sum + dat[2 * k + 2].prefix); } } }
Node query(int index, const int beg, const int end, int l, int r) const { Node ret; if (r <= beg || end <= l) return ret; if (beg <= l && r <= end) return dat[index]; int mid = l + (r - l) / 2; auto vl = query(index * 2 + 1, beg, end, l, mid); auto vr = query(index * 2 + 2, beg, end, mid, r); if (!vr.isValid()) { ret = vl; } else if (!vl.isValid()) { ret = vr; } else { ret.sum = vl.sum + vr.sum; ret.prefix = max(vl.prefix, vl.sum + vr.prefix); } return ret; }
Node queryMin(const int a, const int b) const { return query(0, a, b, 0, n); } };
int main(int argc, char const *argv[]) { int T; cin >> T; for (int iCase = 1; iCase <= T; ++iCase) { int N, S; cin >> N >> S; vector<int> A(N), events(N); unordered_map<int, vector<int>> types; for (int i = 0; i < N; ++i) { cin >> A[i]; types[A[i]].push_back(i); if (types[A[i]].size() <= S) { events[i] = 1; } else if (types[A[i]].size() == S + 1) { events[i] = -S; } else { events[i] = 0; } } SegmentTree st(N, events.data()); int ans = numeric_limits<int>::min(); for (int i = 0; i < N; ++i) { auto r = st.queryMin(i, N); ans = max(ans, r.prefix); auto &v = types[A[i]]; auto it = lower_bound(v.begin(), v.end(), i); if (it + S < v.end()) { st.update(*(it + S), 1); if (it + S + 1 < v.end()) st.update(*(it + S + 1), -S); } } cout << "Case #" << iCase << ": " << ans << endl; } return 0; }
|