Submission #529589

#TimeUsernameProblemLanguageResultExecution timeMemory
529589c28dnv9q3Financial Report (JOI21_financial)C++17
5 / 100
693 ms56380 KiB
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <algorithm>
#include <numeric>
#include <vector>
#include <set>

#define MAX_N 300000

int vals[MAX_N], num_vals;
int scores[MAX_N];

struct node {
    int left, right;
    struct node *parent, *lchild, *rchild;

    int max;
} npool[MAX_N*2], *next_node = npool;
struct node *nmap[MAX_N];

struct node *create_tree(int l, int r, struct node *p = NULL) {
    assert(0 <= l && l < r && r <= num_vals);

    assert(next_node < npool + MAX_N*2);
    struct node *n = next_node++;

    n->left = l;
    n->right = r;
    n->parent = p;
    if(l == r-1) {
        n->lchild = NULL;
        n->rchild = NULL;
        n->max = 0;
        nmap[l] = n;
    } else {
        int m = l + (r - l) / 2;
        n->lchild = create_tree(l, m, n);
        n->rchild = create_tree(m, r, n);
        n->max = 0;
    }

    return n;
}

int query_tree(struct node *node, int l, int r) {
    if(r <= node->left || node->right <= l) return 0;
    if(l <= node->left && node->right <= r) return node->max;
    return std::max(query_tree(node->lchild, l, r), query_tree(node->rchild, l, r));
}

void activate_node(struct node *n) {
    assert(n->left == n->right - 1);

    n->max = scores[n->left];
    for(n = n->parent; n != NULL; n = n->parent) {
        n->max = std::max(n->lchild->max, n->rchild->max);
    }
}

struct nodeb {
    int left, right;
    struct nodeb *lchild, *rchild;

    int lazy_add;
    int max_bctr, max_bctr_idx;
} npoolb[2*MAX_N], *next_nodeb = npoolb;

static inline void update_lazyb(struct nodeb *n) {
    n->max_bctr += n->lazy_add;
    if(n->lchild != NULL) n->lchild->lazy_add += n->lazy_add;
    if(n->rchild != NULL) n->rchild->lazy_add += n->lazy_add;
    n->lazy_add = 0;
}

struct nodeb *create_treeb(int l, int r) {
    assert(0 <= l && l < r && r <= num_vals);

    assert(next_nodeb < npoolb + MAX_N*2);
    struct nodeb *n = next_nodeb++;

    n->left = l;
    n->right = r;
    n->lazy_add = 0;
    if(l == r-1) {
        n->lchild = NULL;
        n->rchild = NULL;
        n->max_bctr = 0;
        n->max_bctr_idx = l;
    } else {
        int m = l + (r - l) / 2;
        n->lchild = create_treeb(l, m);
        n->rchild = create_treeb(m, r);
        n->max_bctr = 0;
        n->max_bctr_idx = r-1;
    }

    return n;
}

void activate_nodeb(struct nodeb *node, int l, int r) {
    update_lazyb(node);

    if(r <= node->left || node->right <= l) return;
    if(l <= node->left && node->right <= r) {
        node->lazy_add++;
        update_lazyb(node);
        return;
    }

    activate_nodeb(node->lchild, l, r);
    activate_nodeb(node->rchild, l, r);

    if(node->lchild->max_bctr >= node->rchild->max_bctr) {
        node->max_bctr = node->lchild->max_bctr;
        node->max_bctr_idx = node->lchild->max_bctr_idx;
    } else {
        node->max_bctr = node->lchild->max_bctr;
        node->max_bctr_idx = node->lchild->max_bctr_idx;
    }
}

struct t {
    int bctr, idx;
};

struct t query_treeb(struct nodeb *node, int s) {
    update_lazyb(node);

    if(node->right <= s) return {-1, -1};
    if(s <= node->left) return {node->max_bctr, node->max_bctr_idx};

    t l = query_treeb(node->lchild, s), r = query_treeb(node->rchild, s);

    if(l.bctr >= r.bctr) return l;
    else return r;
}

int main() {
    int D;
    assert(scanf("%d %d", &num_vals, &D) == 2);
    assert(1 <= num_vals && num_vals <= MAX_N);

    for(int i = 0; i < num_vals; i++) assert(scanf("%d", vals+i) == 1);

    std::vector<int> svidx(num_vals);
    std::iota(svidx.begin(), svidx.end(), 0);
    std::sort(svidx.begin(), svidx.end(), [](int i1, int i2) { 
        if(vals[i1] == vals[i2]) return i1 < i2;
        return vals[i1] > vals[i2]; 
    });

    struct node *tree = create_tree(0, num_vals);
    struct nodeb *treeb = create_treeb(0, num_vals);

    for(auto i : svidx) {
        t t = query_treeb(treeb, i);
        if(t.idx < 0) t.idx = i;

        scores[i] = 1 + query_tree(tree, i+1, t.idx+D+1);
        activate_node(nmap[i]);
        activate_nodeb(treeb, i-D+1, i+D);
    }

    printf("%d\n", *std::max_element(scores, scores+num_vals));
    return EXIT_SUCCESS;
}
#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...