제출 #766028

#제출 시각아이디문제언어결과실행 시간메모리
766028fatemetmhr게임 (IOI13_game)C++17
100 / 100
5297 ms128576 KiB
//  ~ Be Name Khoda ~  //
 
#include "game.h"
#include <bits/stdc++.h>
//#pragma GCC optimize ("O3")
//#pragma GCC target("avx2")
//#pragma GCC optimize("unroll-loops,Ofast")
 
using namespace std;
 
typedef long long ll;
 
#define pb       push_back
#define mp       make_pair
#define all(x)   x.begin(), x.end()
#define fi       first
#define se       second
 
const int maxn  =  1e6   + 10;
const int maxn5 =  5e5   + 10;
const int maxnt =  2e7;
const int maxn3 =  1e3   + 10;
const int mod   =  1e9   + 7;
const ll  inf   =  1e18;

int tt = 0;
 
 
long long gcd2(long long X, long long Y) {
    long long tmp;
    while (X != Y && Y != 0) {
        tmp = X;
        X = Y;
        Y = tmp % Y;
    }
    return X;
}
 
namespace seg{
    int n, m, newnode = 2, innernode = 2, inner[maxnt];
    int chil[maxnt][2], innerchil[maxnt][2];
    ll g[maxnt];
    void innerupdbase(int l, int r, int id, ll val, int v){
        //cout << "inner upd with " << l << ' ' << r << ' ' << id << ' ' << val << ' ' << v << endl;
        if(r - l == 1){
            g[v] = val;
            return;
        }
        int mid = (l + r) >> 1;
        if(id < mid){
            if(!innerchil[v][0])
                innerchil[v][0] = innernode++;
            innerupdbase(l, mid, id, val, innerchil[v][0]);
        }
        else{
            if(!innerchil[v][1])
                innerchil[v][1] = innernode++;
            innerupdbase(mid, r, id, val, innerchil[v][1]);
        }
        g[v] = gcd2(g[innerchil[v][0]], g[innerchil[v][1]]);
        //cout << "ok " << l << ' ' << r << ' ' << val << ' ' << v << ' ' << g[v] << ' ' << g[innerchil[v][1]] << ' ' << g[innerchil[v][0]] << endl;
    }
 
    void innerupdult(int l, int r, int id, int v1, int v2, int v3){
        g[v1] = gcd2(g[v2], g[v3]);
        if(r - l == 1)
            return;
        int mid = (l + r) >> 1;
        if(id < mid){
            if(!innerchil[v1][0])
                innerchil[v1][0] = innernode++;
            innerupdult(l, mid, id, innerchil[v1][0], innerchil[v2][0], innerchil[v3][0]);
        }
        else{
            if(!innerchil[v1][1])
                innerchil[v1][1] = innernode++;
            innerupdult(mid, r, id, innerchil[v1][1], innerchil[v2][1], innerchil[v3][1]);
        }
    }
 
 
    ll innerget(int l, int r, int lq, int rq, int v){
        if(v == 0 || rq <= l || r <= lq)
            return 0;
        if(lq <= l && r <= rq){
            //cout << "inner getting " << l << ' ' << r << ' ' << lq << ' ' << rq << ' ' << v << ' ' << g[v] << endl;
            return g[v];
        }
        int mid = (l + r) >> 1;
        return gcd2(innerget(l, mid, lq, rq, innerchil[v][0]), innerget(mid, r, lq, rq, innerchil[v][1]));
    }
 
 
    void upd(int l, int r, int id, int id2, ll val, int v){
        if(!inner[v])
            inner[v] = innernode++;
        //cout << "entering iiner update " << l << ' ' << r << ' ' << v << ' ' << inner[v] << ' ' << val << endl;
        if(r - l == 1){
            innerupdbase(0, m, id2, val, inner[v]);
            return;
        }
        int mid = (l + r) >> 1;
        if(id < mid){
            if(!chil[v][0])
                chil[v][0] = newnode++;
            upd(l, mid, id, id2, val, chil[v][0]);
        }
        else{
            if(!chil[v][1])
                chil[v][1] = newnode++;
            upd(mid, r, id, id2, val, chil[v][1]);
        }
        innerupdult(0, m, id2, inner[v], inner[chil[v][0]], inner[chil[v][1]]);
    }
 
    ll get(int l, int r, int lq, int rq, int llq, int rrq, int v){
        if(v == 0 || rq <= l || r <= lq)
            return 0;
        if(lq <= l && r <= rq){
            if(!inner[v])
                return 0;
            ll ret = innerget(0, m, llq, rrq, inner[v]);
            //cout << "here " << l << ' ' << r << ' ' << lq << ' ' << rq << ' ' << v << ' ' << ret << endl;
            return ret;
        }
        int mid = (l + r) >> 1;
        return gcd2(get(l, mid, lq, rq, llq, rrq, chil[v][0]), get(mid, r, lq, rq, llq, rrq, chil[v][1]));
    }
 
    inline void clear(int nn, int mm){
        n = nn;
        m = mm;
        for(int i = 0; i < newnode; i++)
            inner[i] = chil[i][0] = chil[i][1] = 0;
        for(int i = 0; i < innernode; i++)
            innerchil[i][0] = innerchil[i][1] = g[i] = 0;
        newnode = innernode = 2;
    }
}
 
int szx, szy, n, m;
int newnode = 2, innernode = 2, inner[maxnt];
int chil[maxnt][2], innerchil[maxnt][2];
ll g[maxnt];
vector <int> avx, avy;
map <pair<int, int>, ll> av;
set <pair<int, int>> avseg;
 
void innerupdbase(int l, int r, int id, ll val, int v){
    //cout << "inner upd with " << l << ' ' << r << ' ' << id << ' ' << val << ' ' << v << endl;
    if(r - l == 1){
        g[v] = val;
        return;
    }
    int mid = (l + r) >> 1;
    if(id < mid){
        if(!innerchil[v][0])
            innerchil[v][0] = innernode++;
        innerupdbase(l, mid, id, val, innerchil[v][0]);
    }
    else{
        if(!innerchil[v][1])
            innerchil[v][1] = innernode++;
        innerupdbase(mid, r, id, val, innerchil[v][1]);
    }
    g[v] = gcd2(g[innerchil[v][0]], g[innerchil[v][1]]);
    //cout << "ok " << l << ' ' << r << ' ' << val << ' ' << v << ' ' << g[v] << ' ' << g[innerchil[v][1]] << ' ' << g[innerchil[v][0]] << endl;
}
 
void innerupdult(int l, int r, int id, int v1, int v2, int v3){
    g[v1] = gcd2(g[v2], g[v3]);
    if(r - l == 1)
        return;
    int mid = (l + r) >> 1;
    if(id < mid){
        if(!innerchil[v1][0])
            innerchil[v1][0] = innernode++;
        innerupdult(l, mid, id, innerchil[v1][0], innerchil[v2][0], innerchil[v3][0]);
    }
    else{
        if(!innerchil[v1][1])
            innerchil[v1][1] = innernode++;
        innerupdult(mid, r, id, innerchil[v1][1], innerchil[v2][1], innerchil[v3][1]);
    }
}
 
 
ll innerget(int l, int r, int lq, int rq, int v){
    if(v == 0 || rq <= l || r <= lq)
        return 0;
    if(lq <= l && r <= rq){
        //cout << "inner getting " << l << ' ' << r << ' ' << lq << ' ' << rq << ' ' << v << ' ' << g[v] << endl;
        return g[v];
    }
    int mid = (l + r) >> 1;
    return gcd2(innerget(l, mid, lq, rq, innerchil[v][0]), innerget(mid, r, lq, rq, innerchil[v][1]));
}
 
 
void upd(int l, int r, int id, int id2, ll val, int v){
    if(!inner[v])
        inner[v] = innernode++;
    //cout << "entering iiner update " << l << ' ' << r << ' ' << v << ' ' << inner[v] << ' ' << val << endl;
    if(r - l == 1){
        innerupdbase(0, m, id2, val, inner[v]);
        return;
    }
    int mid = (l + r) >> 1;
    if(id < mid){
        if(!chil[v][0])
            chil[v][0] = newnode++;
        upd(l, mid, id, id2, val, chil[v][0]);
    }
    else{
        if(!chil[v][1])
            chil[v][1] = newnode++;
        upd(mid, r, id, id2, val, chil[v][1]);
    }
    innerupdult(0, m, id2, inner[v], inner[chil[v][0]], inner[chil[v][1]]);
}
 
ll get(int l, int r, int lq, int rq, int llq, int rrq, int v){
    if(v == 0 || rq <= l || r <= lq)
        return 0;
    if(lq <= l && r <= rq){
        if(!inner[v])
            return 0;
        ll ret = innerget(0, m, llq, rrq, inner[v]);
        //cout << "here " << l << ' ' << r << ' ' << lq << ' ' << rq << ' ' << v << ' ' << ret << endl;
        return ret;
    }
    int mid = (l + r) >> 1;
    return gcd2(get(l, mid, lq, rq, llq, rrq, chil[v][0]), get(mid, r, lq, rq, llq, rrq, chil[v][1]));
}
 
void init(int R, int C) {
    n = R;
    m = C;
    /* ... */
}
 
 
inline void rebuild(){
    sort(all(avx));
    sort(all(avy));
    avx.resize(unique(all(avx)) - avx.begin());
    avy.resize(unique(all(avy)) - avy.begin());
    szx = avx.size();
    szy = avy.size();
 
    for(int i = 0; i < newnode; i++)
        inner[i] = chil[i][0] = chil[i][1] = 0;
    for(int i = 0; i < innernode; i++)
        innerchil[i][0] = innerchil[i][1] = g[i] = 0;
    newnode = innernode = 2;
    seg::clear(szx, szy);
    for(auto it = av.begin(); it != av.end(); it++){
        avseg.insert(it->fi);
        int ptx = lower_bound(avx.begin(), avx.begin() + szx, (it->fi).fi) - avx.begin();
        int pty = lower_bound(avy.begin(), avy.begin() + szy, (it->fi).se) - avy.begin();
        seg::upd(0, szx, ptx, pty, it->se, 1);
    }
}

int opt = 0;

void update(int x, int y, long long k) {
    opt++;
    if(newnode > 5e6 || innernode > 5e6)
        rebuild();
    if(avseg.find(mp(x, y)) != avseg.end()){
        av[{x, y}] = k;
        x = lower_bound(avx.begin(), avx.begin() + szx, x) - avx.begin();
        y = lower_bound(avy.begin(), avy.begin() + szy, y) - avy.begin();
        seg::upd(0, szx, x, y, k, 1);
        return;
    }
    upd(0, n, x, y, k, 1);
    av[{x, y}] = k;
    avx.pb(x);
    avy.pb(y);
}
 
long long calculate(int l, int d, int r, int u) {

    tt++;
 
    ll ans = get(0, n, l, r + 1, d, u + 1, 1);
    //if(tt == 129048)
    //    cerr << l << ' ' << r << ' ' << d << ' ' << u << endl;
    l = lower_bound(avx.begin(), avx.begin() + szx, l) - avx.begin();
    r = upper_bound(avx.begin(), avx.begin() + szx, r) - avx.begin();
    d = lower_bound(avy.begin(), avy.begin() + szy, d) - avy.begin();
    u = upper_bound(avy.begin(), avy.begin() + szy, u) - avy.begin();
    ans = gcd2(ans, seg::get(0, szx, l, r, d, u, 1));
    //if(tt == 129048)
    //    cerr << newnode << ' ' << innernode << ' ' << ans << ' ' << opt << ' ' << l << ' ' << r << ' ' << d << ' ' << u << endl;
    return ans;
}









#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...