Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include <iostream>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <map>
- #include <chrono>
- #include <unordered_map>
- #include <list>
- #include <numeric>
- #include <set>
- #include <algorithm>
- #include <unordered_set>
- #include <assert.h>
- #include <fstream>
- #include <sstream>
- using namespace std;
- #define vi vector<int>
- #define vec vector
- #define F first
- #define S second
- vi merge_upd(const vi& a, const vi& b) {
- int l = 0, r = 0;
- vi res;
- while (l < a.size() && r < b.size()) {
- if (a[l] < b[r]) {
- res.push_back(a[l++]);
- }
- else {
- res.push_back(b[r++]);
- }
- }
- while (l < a.size()) res.push_back(a[l++]);
- while (r < b.size()) res.push_back(b[r++]);
- return res;
- }
- vec<vi> t;
- void build(vi a) {
- while ((a.size() & (a.size() - 1))) a.push_back(0);
- t.resize(a.size() << 1);
- for (int i = 0; i < a.size(); ++i) {
- t[i + a.size()] = { a[i] };
- }
- for (int i = a.size() - 1; i > 0; --i) {
- t[i] = merge_upd(t[i * 2], t[i * 2 + 1]);
- }
- }
- int query(int v, int vl, int vr, int l, int r) {
- if (vl > vr || l > vr || r < vl) return {};
- if (l <= vl && vr <= r) {
- int i = upper_bound(t[v].begin(), t[v].end(), r) - t[v].begin();
- return t[v].size() - i;
- }
- int m = (vl + vr) >> 1;
- return query(v * 2, vl, m, l, r) + query(v * 2 + 1, m + 1, vr, l, r);
- }
- vec<pair<int, int>> T;
- void build2(vec<pair<int, int>> a) {
- while ((a.size() & (a.size() - 1))) a.push_back({ -1e9, a.size() });
- T.resize(a.size() << 1);
- for (int i = 0; i < a.size(); ++i) {
- T[i + a.size()] = { a[i] };
- }
- for (int i = a.size() - 1; i > 0; --i) {
- T[i] = max(T[i * 2], T[i * 2 + 1]);
- }
- }
- pair<int, int> query2(int v, int vl, int vr, int l, int r) {
- if (vl > vr || l > vr || r < vl) return {};
- if (l <= vl && vr <= r) {
- return T[v];
- }
- int m = (vl + vr) >> 1;
- return max(query2(v * 2, vl, m, l, r), query2(v * 2 + 1, m + 1, vr, l, r));
- }
- pair<int, int> go(vi& a, int L, int R, int A, int B) {
- vi b(a.size());
- unordered_map<int, int> pos;
- vec<pair<int, int>> pref(a.size());
- int s = 0;
- for (int i = a.size() - 1; i > -1; --i) {
- if (pos.count(a[i])) {
- b[i] = pos[a[i]];
- }
- else b[i] = a.size();
- pos[a[i]] = i;
- }
- for (int i = 0; i < a.size(); ++i) {
- s += a[i];
- pref[i] = { s, i };
- }
- build(b);
- build2(pref);
- int mx = -1e9;
- int al = -1, ar = -1;
- for (int i = 0; i < a.size() - R + 1; ++i) {
- // Давайте найдем такое самое правое l, что кол-во различных на
- // отрезке от i до l <= B
- int l = i + L, r = i + R;
- while (l < r - 1) {
- int m = (l + r) >> 1;
- if (query(1, 0, (t.size() >> 1) - 1, i, m) > B) r = m;
- else l = m;
- }
- int r1 = query(1, 0, (t.size() >> 1) - 1, i, l);
- // Если кол-во различных на минимальном отрезке от i до i+L < A || > B
- if (r1 > B || r1 < A) continue;
- int xl = l;
- // Давайте найдем такое самое правое l, что кол-во различных на
- // отрезке от i до l <= A
- l = i + L, r = i + R;
- while (l < r - 1) {
- int m = (l + r) >> 1;
- if (query(1, 0, (t.size() >> 1) - 1, i, m) > A) r = m;
- else l = m;
- }
- // Ну если не нашли - ну и ладно
- if (query(1, 0, (t.size() >> 1) - 1, i, l) < A) continue;
- // Найдем максимум на префиксе от l до xl -> это и будет ответом
- auto x = query2(1, 0, (t.size() >> 1) - 1, l, xl);
- int sum = x.first - (i ? pref[i - 1].first : 0);
- if (sum > mx) {
- al = i; ar = x.second;
- mx = sum;
- }
- }
- return { al, ar };
- }
- pair<int, int> go2(vi& a, int L, int R, int A, int B) {
- int mx = -1e9, al = -1, ar = -1;
- for (int i = 0; i < a.size() - R + 1; ++i) {
- unordered_set<int> el;
- int sum = 0;
- for (int j = 0; j < L - 1; ++j) el.insert(a[j + i]), sum += a[j + i];
- for (int j = L - 1; j < R; ++j) {
- sum += a[j + i];
- el.insert(a[j + i]);
- if (A <= el.size() && el.size() <= B) {
- if (sum >= mx) {
- mx = sum;
- al = i;
- ar = i + j;
- }
- }
- }
- }
- return { al, ar };
- }
- signed main() {
- #ifndef _MSVC_LANG
- freopen("painter.in", "r", stdin);
- freopen("painter.out", "w", stdout);
- #endif
- int n, l, r, a, b;
- n = 100;
- l = 2; r = 20;
- a = 1; b = 10;
- vi aa(n);
- int t = 1e5;
- while (t--) {
- for (auto& e : aa)e = rand() % 250;
- if (!(t % 100)) cout << t << "\n";
- auto r1 = go(aa, l, r, a, b);
- auto r2 = go2(aa, l, r, a, b);
- set<int> xa;
- int s = 0;
- for (int j = r1.first; j <= r1.second; ++j)xa.insert(aa[j]), s += aa[j];
- set<int> xb;
- int ss = 0;
- for (int j = r2.first; j <= r2.second; ++j)xb.insert(aa[j]), ss += aa[j];
- if (!(ss == s && a <= xa.size() && xa.size() <= b && a <= xb.size() && xb.size() <= b)) {
- cout << "!";
- assert(false);
- go2(aa, l, r, a, b);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment