Submission #1250640

#TimeUsernameProblemLanguageResultExecution timeMemory
1250640quangminh412Financial Report (JOI21_financial)C++20
100 / 100
1215 ms677956 KiB
/*
  Ben Watson
  Handle codeforces : quangminh98

  Current Theme: Transformers !!!!
*/

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const string name = "test";

void solve();
signed main()
{
    if (fopen((name + ".inp").c_str(), "r"))
    {
        freopen((name + ".inp").c_str(), "r", stdin);
        freopen((name + ".out").c_str(), "w", stdout);
    }
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    solve();

    return 0;
}

// main program
const int oo = 0x3f3f3f3f;
const int maxn = 3e5 + 1;
const int maxbit = 30;
const int N = 548;

struct SegmentTree
{
    struct Node
    {
        int mn, lazy;

        Node(int val) : mn(val), lazy(oo) {};
        Node operator + (const Node& other)
        {
            Node res = Node(oo);
            res.mn = min(mn, other.mn);
            return res;
        }
    };
    vector<Node> st;
    int n;

    SegmentTree(int n) : n(n) { st.resize(4 * n + 1, Node(oo)); }

    void pass(int head, int l, int r)
    {
        if (st[head].lazy == oo)
            return;

        st[head].mn = min(st[head].mn, st[head].lazy);
        if (l != r)
        {
            st[head << 1].lazy = min(st[head << 1].lazy, st[head].lazy);
            st[head << 1 | 1].lazy = min(st[head << 1 | 1].lazy, st[head].lazy);
        }

        st[head].lazy = oo;
    }

    void update(int head, int l, int r, int u, int v, int val)
    {
        pass(head, l, r);
        if (l > v || r < u) return;
        if (u <= l && r <= v)
        {
            st[head].lazy = min(st[head].lazy, val);
            pass(head, l, r);
            return;
        }

        int mid = l + r >> 1;
        update(head << 1, l, mid, u, v, val);
        update(head << 1 | 1, mid + 1, r, u, v, val);
        st[head] = st[head << 1] + st[head << 1 | 1];
    }
    void update(int u, int v, int val) { if (u > v) return; update(1, 1, n, u, v, val); }

    int query(int head, int l, int r, int pos)
    {
        pass(head, l, r);
        if (pos < l || r < pos) return oo;
        if (l == r) return st[head].mn;

        int mid = l + r >> 1;
        if (pos <= mid)
            return query(head << 1, l, mid, pos);
        return query(head << 1 | 1, mid + 1, r, pos);
    }
    int query(int pos) { return query(1, 1, n, pos); }
};

struct NestedFenwickTree
{
    vector<int> bits;
    int n;

    NestedFenwickTree(int n = 0) : n(n) { bits.resize(n + 1, 0); }

    void update(int pos, int val)
    {
        for (; pos <= n; pos += (pos & (-pos)))
            bits[pos] = max(bits[pos], val);
    }

    int query(int pos)
    {
        int res = 0;
        for (; pos > 0; pos -= (pos & (-pos)))
            res = max(res, bits[pos]);
        return res;
    }
};

struct FenwickTree
{
    vector<NestedFenwickTree> bits;
    int n, cur;

    FenwickTree(int n = 0, int cur = 0) : n(n), cur(cur) { bits.resize(n + 1, NestedFenwickTree(cur + 1)); }

    void update(int pos, int x, int val)
    {
        for (; pos <= n; pos += (pos & (-pos)))
            bits[pos].update(cur - x + 1, val);
    }

    int query(int pos, int x)
    {
        int res = 0;
        for (; pos > 0; pos -= (pos & (-pos)))
            res = max(res, bits[pos].query(cur - x));
        return res;
    }
};

int n, d, cur, num;
int block_id[maxn];
map<int, int> cmp;
int a[maxn], dp[maxn], R[maxn];

void solve()
{
    cin >> n >> d;
    cur = 0;
    vector<int> v;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        v.push_back(a[i]);
    }

    // coordinate compression
    sort(v.begin(), v.end());
    cur = 0;
    for (int x : v)
        if (cmp[x] == 0)
            cmp[x] = ++cur;
    // sqrt decomposition
    num = 1;
    for (int i = 1; i <= n; i++)
    {
        block_id[i] = num;
        if (i % N == 0)
            num++;
    }

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    SegmentTree st(cur);
    for (int i = n; i > 0; i--)
    {
        R[i] = n;
        pq.push({a[i], i});
        while (!pq.empty() && pq.top().second >= i + d)
            pq.pop();

        if (i + d <= n)
            R[i] = min(R[i], st.query(cmp[a[i]]));

        if (i + d - 1 <= n)
            st.update(1, cmp[pq.top().first] - 1, i + d - 1);
    }

    int res = 0;
    FenwickTree bit(num, cur);
    for (int i = n; i > 0; i--)
    {
        int mx = 0;

        mx = bit.query(block_id[R[i]] - 1, cmp[a[i]]);
        for (int j = R[i]; j > i && block_id[j] == block_id[R[i]]; j--)
            if (a[j] > a[i])
                mx = max(mx, dp[j]);
        dp[i] = 1 + mx;
        bit.update(block_id[i], cmp[a[i]], dp[i]);
        res = max(res, dp[i]);
    }

    cout << res << '\n';
}

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:20:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   20 |         freopen((name + ".inp").c_str(), "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:21:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   21 |         freopen((name + ".out").c_str(), "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...