Submission #1113707

#TimeUsernameProblemLanguageResultExecution timeMemory
1113707GrayGame (IOI13_game)C++17
100 / 100
5952 ms107592 KiB
#include<bits/stdc++.h>
#include <random>
#include "game.h"
#define ll long long
#define ff first
#define ss second
#define ln "\n"
using namespace std;
mt19937 mt(time(nullptr));
struct Treap{
    struct Node{
        Node *left, *right;
        ll x, y, gcd, fgcd;
        Node(ll _x, ll _gcd){
            left=right=nullptr;
            x=_x; gcd=fgcd=_gcd;
            y=mt();
        }
        Node(ll _x, ll _y, ll _gcd){
            left=right=NULL;
            x=_x; y=_y; gcd=fgcd=_gcd;
        }
    };
    Node * root;
    Treap(){
        root=new Node(-1, 2e18, 0);
    }
    void upd(Node * t){
        if (!t) return;
        t->fgcd=t->gcd;
        if (t->left) t->fgcd=__gcd(t->left->fgcd, t->fgcd);
        if (t->right) t->fgcd=__gcd(t->right->fgcd, t->fgcd);
    }
    void split(Node *par, Node*&wl, Node*&wr, ll x){
        if (!par){
            wl=wr=nullptr;
        }else if (par->x<=x){
            split(par->right, par->right, wr, x); wl=par;
        }else{
            split(par->left, wl, par->left, x); wr=par;
        }
        upd(wl); upd(wr);
    }
    void merge(Node *& npar, Node *l, Node *r){
        if (!l or !r){
            npar=l?l:r;
        }else if (l->y>r->y){
            merge(l->right, l->right, r); npar=l;
        }else{
            merge(r->left, l, r->left); npar=r;
        }
        upd(npar);
    }
    void insert(Node *& cur, Node * item){
        if (!cur){
            cur=item;
        }else if (cur->y>=item->y){
            insert(cur->x<=item->x?cur->right:cur->left, item);
        }else{
            split(cur, item->left, item->right, item->x); cur=item;
        }
        upd(cur);
    }
    ll query_range(Node *& cur, ll l, ll r){
        Node * t1, * t2, * t3;
        split(cur, t1, t2, l-1);
        split(t2, t2, t3, r);
        ll res=t2?t2->fgcd:0;
        merge(cur, t1, t2);
        merge(cur, cur, t3);
        return res;
    }
    void update(Node * cur, ll x, ll newval){
        if (!cur){
            insert(root, new Node(x, newval));
            return;
        }else if (cur->x==x){
            cur->gcd=newval;
        }else if (cur->x<x){
            update(cur->right, x, newval);
        }else{
            update(cur->left, x, newval);
        }
        upd(cur);
    }
    void update(ll x, ll newval){
        update(root, x, newval);
    }
    void insert(ll x, ll val){
        insert(root, new Node(x, val));
    }
    ll query(ll l, ll r){
        return query_range(root, l, r);
    }
};

// struct SegTree1D{
// 	struct Node{
// 		ll left, right, val;
// 		Node(){
// 			left=right=-1;
// 			val=0;
// 		}
// 	};
// 	vector<Node> nodes;
// 	ll add_node(){
// 	    nodes.push_back(Node());
// 		return nodes.size()-1;
// 	}
// 	map<int, ll> leaves;
// 	int rsz;
// 	SegTree1D(int N){
// 		rsz=N;
// 		add_node();
// 	}
// 	void update(ll tl, ll tr, ll v, ll i, ll x){
// 	    if (tl==tr){
// 			nodes[v].val=x;
// 			leaves[tl]=v;
// 		}else{
// 		    ll tm = (tl+tr)/2;
// 			if (i<=tm){
// 			    if (nodes[v].left==-1) nodes[v].left=add_node();
// 				update(tl, tm, nodes[v].left, i, x);
// 			}else{
// 			    if (nodes[v].right==-1) nodes[v].right=add_node();
// 				update(tm+1, tr, nodes[v].right, i, x);
// 			}
// 			nodes[v].val=0;
// 			if (nodes[v].left!=-1) nodes[v].val=__gcd(nodes[nodes[v].left].val, nodes[v].val);
// 			if (nodes[v].right!=-1) nodes[v].val=__gcd(nodes[nodes[v].right].val, nodes[v].val);
// 		}
// 	}
// 	void update(ll i, ll x){
// 	   update(0, rsz-1, 0, i, x);
// 	}
// 	ll query(ll tl, ll tr, ll v, ll l, ll r){
// 	    if (tl==l and tr==r){
// 			return nodes[v].val;
// 		}
// 		else if (l>r) return 0;
// 		else{
// 		    ll tm = (tl+tr)/2;
// 			ll res=0;
// 			if (nodes[v].left!=-1) res=__gcd(res, query(tl, tm, nodes[v].left, l, min(r, tm)));
// 			if (nodes[v].right!=-1) res=__gcd(res, query(tm+1, tr, nodes[v].right, max(l, tm+1), r));
// 			return res;
// 		}
// 	}
// 	ll query(int l, int r){
// 		return query(0, rsz-1, 0, l, r);
// 	}
// 	ll getval(int ind){
// 		if (!leaves.count(ind)) return 0;
// 		return nodes[leaves[ind]].val;
// 	}
// };
struct SegTree2D{
	struct mNode{
		mNode *left, *right;
		Treap *val;
		int csz;
		mNode(int _csz){
			csz=_csz;
			left=right=nullptr;
			val = new Treap();
		}
		void update(int tl, int tr, int i, int j, ll x){
			if (tl==tr){
			    // cout << "Entered" << endl;
				val->update(j, x);
				// cout << "Exited"<< endl;
			}else{
				int tm = (tl+tr)/2;
				if (i<=tm){
					if (!left) left=new mNode(csz);
					left->update(tl, tm, i, j, x);
				}else{
					if (!right) right=new mNode(csz);
					right->update(tm+1, tr, i, j, x);
				}
				val->update(j, __gcd((left?left->val->query(j, j):0), (right?right->val->query(j, j):0)));
			}
		}
		ll query(int li, int ri, int lj, int rj, int tl, int tr){
			if (tl==li and tr==ri){
			    // cout << lj << "-" << rj << endl;
				ll res= val->query(lj, rj);
				// cout << "Success" << endl;
				return res;
			}else if (li>ri) return 0;
			else{
				ll ret=0;
				int tm = (tl+tr)/2;
				if (left and li<=min(ri, tm)) ret=__gcd(ret, left->query(li, min(ri, tm), lj, rj, tl, tm));
				if (right and max(li, tm+1)<=ri) ret=__gcd(ret, right->query(max(li, tm+1), ri, lj, rj, tm+1, tr));
				return ret;
			}
		}
	};
	mNode * root;
	ll csz, rsz;
	void init(int R, int C){
		rsz=R; csz=C;
		root = new mNode(csz);
	}
	void update(int i, int j, ll x){
		root->update(0, rsz-1, i, j, x);
	}
	ll query(int li, int ri, int lj, int rj){
		return root->query(li, ri, lj, rj, 0, rsz-1);
	}
} DS;


void init(int R, int C) {
	DS.init(R, C);
	// cout << "Init" << endl;
}

void update(int P, int Q, long long K) {
    // cout << "Updating " << P << "-" << Q << "-" << K << endl;
	DS.update(P, Q, K);
	// cout << "Updated " << P << "-" << Q << "-" << K << endl;
}

long long calculate(int P, int Q, int U, int V) {
	/* ... */
	ll res= DS.query(P, U, Q, V);
	// cout << "Queried" << endl;
	return res;
	// return 0;
}
#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...