Submission #1160958

#TimeUsernameProblemLanguageResultExecution timeMemory
1160958SmuggingSpunGame (IOI13_game)C++20
100 / 100
2173 ms62780 KiB
#include "game.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd2(ll X, ll Y){
    ll tmp;
    while (X != Y && Y != 0) {
        tmp = X;
        X = Y;
        Y = tmp % Y;
    }
    return X;
}
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
struct Treap_Node{
    int pri, mn, mx, pos;
    ll val, g;
    Treap_Node *l, *r;
    Treap_Node(){
        this->l = this->r = nullptr;
    }
    Treap_Node(int pos, ll val){
        this->l = this->r = nullptr;
        this->pri = rng();
        this->mn = this->mx = this->pos = pos;
        this->val = this->g = val;
    }
    void update(){
        g = val;
        mn = mx = pos;
        if(l != nullptr){
            g = gcd2(g, l->g);
            mn = l->mn;
        }
        if(r != nullptr){
            g = gcd2(g, r->g);
            mx = r->mx;
        }
    }
};
struct Treap{
    Treap_Node *root;
    Treap(){
        this->root = nullptr;
    }
    void split(Treap_Node *n, Treap_Node *&l, Treap_Node *&r, int pos){
        if(n == nullptr){
            l = r = nullptr;
            return;
        }
        if(n->pos < pos){
            split(n->r, n->r, r, pos);
            l = n;
        }
        else{
            split(n->l, l, n->l, pos);
            r = n;
        }
        n->update();
    }
    void merge(Treap_Node *&n, Treap_Node *l, Treap_Node *r){
        if(l == nullptr){
            n = r;
            return;
        }
        if(r == nullptr){
            n = l;
            return;
        }
        if(l->pri < r->pri){
            merge(l->r, l->r, r);
            n = l;
        }
        else{
            merge(r->l, l, r->l);
            n = r;
        }
        n->update();
    }
    bool find(int pos){
        Treap_Node *n = root;
        while(n != nullptr){
            if(n->pos == pos){
                return true;
            }
            n = (n->pos < pos ? n->r : n->l);
        }
        return false;
    }
    void update(Treap_Node *n, int pos, ll val){
        if(n->pos == pos){
            n->val = val;
        }
        else if(n->pos < pos){
            update(n->r, pos, val);
        }
        else{
            update(n->l, pos, val);
        }
        n->update();
    }
    void insert(int pos, ll val){
        if(find(pos)){
            update(root, pos, val);
            return;
        }
        Treap_Node *a, *b;
        split(root, a, b, pos);
        merge(root, a, new Treap_Node(pos, val));
        merge(root, root, b);
    }
    ll query(Treap_Node *n, int u, int v){
        if(n != nullptr){
            //cout << u << " " << v << " " << n->mx << " " << n->mn << " | " << n->pos << " " << n->val << " " << n->g << endl;
        }
        if(n == nullptr || n->mx < u || n->mn > v){
            return 0;
        }
        if(u <= n->mn && v >= n->mx){
            return n->g;
        }
        ll ans = gcd2(query(n->l, u, v), query(n->r, u, v));
        if(u <= n->pos && v >= n->pos){
            ans = gcd2(ans, n->val);
        }
        return ans;
    }
    ll query(int u, int v){
        return root == nullptr ? 0 : query(root, u, v);
    }
};
int cnt_st_node = 0;
struct Segment_Tree{
    Treap treap;
    Segment_Tree *l, *r;
    int low, high;
    Segment_Tree(){
        this->l = this->r = nullptr;
    }
    Segment_Tree(int low, int high){
        this->l = this->r = nullptr;
        this->low = low;
        this->high = high;
    }
    void fix(int pos){
        ll val = 0;
        if(l != nullptr){
            val = gcd2(val, l->treap.query(pos, pos));
        }
        if(r != nullptr){
            val = gcd2(val, r->treap.query(pos, pos));
        }
        treap.insert(pos, val);
    }
    void new_left(){
        if(l == nullptr){
            l = new Segment_Tree(low, (low + high) >> 1);
        }       
    }
    void new_right(){
        if(r == nullptr){
            r = new Segment_Tree(((low + high) >> 1) + 1, high);
        }
    }
    void update(int x, int y, ll val){
        if(low == high){
            treap.insert(y, val);
            return;
        }
        if(x > ((low + high) >> 1)){
            new_right();
            r->update(x, y, val);
        }
        else{
            new_left();
            l->update(x, y, val);
        }
        fix(y);
    }
    ll query(int x, int y, int u, int v){
        if(low > u || high < x){
            return 0;
        }
        if(x <= low && u >= high){
            return treap.query(y, v);
        }
        ll g = 0;
        if(l != nullptr){
            g = gcd2(g, l->query(x, y, u, v));
        }
        if(r != nullptr){
            g = gcd2(g, r->query(x, y, u, v));
        }
        return g;
    }
};
Segment_Tree st;
void init(int R, int C){
    st = Segment_Tree(0, R - 1);
}
void update(int P, int Q, ll K){
    st.update(P, Q, K);
    // cout << " ||| " << endl;
    // ll temp = st.query(P, Q, P, Q);
    // cout << temp << " ||||| " << endl;
}
ll calculate(int P, int Q, int U, int V){
    return st.query(P, Q, U, V);
}
#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...