제출 #1354228

#제출 시각아이디문제언어결과실행 시간메모리
1354228tasso7사다리꼴 (balkan11_trapezoid)C++20
10 / 100
1098 ms41788 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 30013
struct Treap{
    int idx = 0;
    int value = -1;
    int priority;
    int sum_over_childerns = -1;
    Treap *left = nullptr, *right = nullptr;

    Treap(){
        priority = rand();
    }

    Treap(int i, int v){
        priority = rand();
        idx = i;
        value = (sum_over_childerns = v);
    }

    Treap* join(Treap* l, Treap* r){
        left = l;
        right = r;
        sum_over_childerns = value % mod;
        if(l != nullptr) {sum_over_childerns += l->sum_over_childerns;}
        sum_over_childerns %= mod;
        if(r != nullptr) {sum_over_childerns += r->sum_over_childerns;}
        sum_over_childerns %= mod;
        return this;
    }
};

pair<Treap*, Treap*> split(Treap* t, int threshold){
    if(t == nullptr) return {nullptr, nullptr};
    if(threshold > t->idx){
        auto[l, r] = split(t->right, threshold);
        return {t->join(t->left, l), r};
    }else{
        auto[l, r] = split(t->left, threshold);
        return {l, t->join(r, t->right)};
    }
}

Treap* merge(Treap* a, Treap* b){
    if(a == nullptr) return b;
    if(b == nullptr) return a;
    if(a->priority > b->priority){
        return a->join(a->left, merge(a->right, b));
    }else{
        return b->join(merge(a, b->left), b->right);
    }
}

Treap* treap_pool;
int amount_left = 0;
Treap* t_gen(){
    if(amount_left == 0){
        treap_pool = new Treap[100000];
        amount_left = 100000;
    }
    amount_left--;
    return treap_pool++; 
}

Treap* insertN(Treap *& t, Treap* node){
    if (t == nullptr) return t=node;

    if (node->priority > t->priority) {
        auto [l, r] = split(t, node->idx);
        return t=node->join(l,r);
    }

    if (node->idx < t->idx)
        return t->join(insertN(t->left, node), t->right);    
    else
        return t->join(t->left, insertN(t->right, node));    
}

Treap* insert(Treap *& t, int idx, int value){
    Treap* node = t_gen();
    *node = Treap(idx, value);
    return insertN(t, node);
}

int queryTreap(Treap*& t, int q){
     if(t == nullptr) return 0;

    if(t->idx >= q){
        int right_sum = t->right ? t->right->sum_over_childerns : 0;
        return (t->value + right_sum + queryTreap(t->left, q)) % mod;
    }else{
        return queryTreap(t->right, q);
    }
}


struct segTree{
    vector<int> values;
    int s = 0;

    void u(int n, int l, int r, int i, int x){
        if(i < l || r <= i){return;}
        if(r-l==1){
            values[n] = x;
            return;
        }
        int m = (l+r)/2;
        u(2*n, l, m, i, x); u(2*n+1, m, r, i, x);
        values[n] = max(values[2*n], values[2*n+1]);
    }

    int q(int n, int l, int r, int ql, int qr){
        if(ql <= l && r <= qr){return values[n];}
        if(r <= ql || qr <= l){return 0;}
        int m = (l+r)/2;
        return max(q(2*n, l, m, ql, qr), q(2*n+1, m, r, ql, qr));
    }

    
    void update(int i, int x){
        u(1, 0, s, i, x);
    }
    
    int query(int l, int r){
        return q(1, 0, s, l, r);
    }

    segTree(int n){
        s = 1;
        while(s < n) s <<= 1;
        values.resize(4*s);
        fill(values.begin(), values.end(), 0);
    }
};


int main(){
    srand(time(NULL));
    int N;
    cin >> N;
    vector<array<ll, 4>> trapezoids(N);
    
    // INPUT AND CHANGE OF VAR
    {set<ll> trapezoids_var_change;
    for(int i = 0; i < N; i++){
        ll a, b, c, d; cin >> a >> b >> c >> d;
        trapezoids[i] = {a,b,c,d};
        trapezoids_var_change.insert(a);
        trapezoids_var_change.insert(b);
        trapezoids_var_change.insert(c);
        trapezoids_var_change.insert(d);
    }

    map<ll,int> idx_changer;
    for(auto a = trapezoids_var_change.begin(); a != trapezoids_var_change.end(); a++){
        idx_changer[*a] = idx_changer.size();
    }
    for(int i = 0; i < N; i++){
        auto[a,b,c,d] = trapezoids[i];
        trapezoids[i] = {idx_changer[a],idx_changer[b],idx_changer[c],idx_changer[d]};
    }}

    sort(trapezoids.begin(), trapezoids.end());

    vector<int> QID(trapezoids.size());
    for(int i = 0; i < QID.size(); i++){QID[i] = i;}
    
    sort(QID.begin(), QID.end(), [&trapezoids](int a, int b){return trapezoids[a][1]<trapezoids[b][1];});

    segTree seg(4*N+1);
    vector<int> para_seg(N, 0);

    vector<Treap*> startes_for_amount(N+1);
    for(int i = 0; i <= N; i++) startes_for_amount[i] = nullptr;

    vector<int> number_of_solutions_of_i(N, 0);

    int insert_id = N-1;
    int query_id = N-1;
    while(insert_id >= 0 || query_id >= 0){
        // if after inserting insert_id i can still query query_id then i'll insert; otherwise query
        if(insert_id== -1 || query_id == -1 || (insert_id != -1 && (trapezoids[insert_id][0] >= trapezoids[QID[query_id]][1]))){
            // INSERT
            seg.update(trapezoids[insert_id][2], max(1,para_seg[insert_id]));
            insert(startes_for_amount[para_seg[insert_id]], trapezoids[insert_id][2], number_of_solutions_of_i[insert_id]);
            insert_id--;
        }else{
            // QUERY
            para_seg[QID[query_id]] = seg.query(trapezoids[QID[query_id]][3]+1, 4*N+1) + 1;
            number_of_solutions_of_i[QID[query_id]] = max(1,queryTreap(startes_for_amount[para_seg[QID[query_id]]-1],trapezoids[QID[query_id]][3]+1)); // somma dei modi con tutti gli starter successivi
            query_id--;
        }
        for(auto a : para_seg) cerr << a << " "; cerr << endl;
        for(auto a : number_of_solutions_of_i) cerr << a << " "; cerr << endl;
        cerr << endl;
    }

    int sol = seg.query(0, 4*N+1);
    cout << sol << " " << startes_for_amount[sol]->sum_over_childerns;

    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…