Submission #274893

#TimeUsernameProblemLanguageResultExecution timeMemory
274893dooweyI want to be the very best too! (NOI17_pokemonmaster)C++14
47 / 100
5101 ms501464 KiB
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define fi first
#define se second
#define mp make_pair
#define fastIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int N = 50010;
const int K = N * 2;

int cur;
int n, m;

int getid(int x, int y){
    return (x - 1) * m + y;
}

int vl[K];
int par[K];
bool active[N];
vector<int> T[N];

int dir[4][2] = {{-1,0},{+1,0},{0,-1},{0,+1}};

int fin(int x){
    if(par[x]==x)return x;
    return par[x]=fin(par[x]);
}

vector<int> E[K];

void unite(int u, int v){
    u = fin(u);
    v = fin(v);
    if(u == v)
        return;
    cur ++ ;
    vl[cur] = max(vl[u], vl[v]);
    E[cur].push_back(u);
    E[cur].push_back(v);
    par[u] = cur;
    par[v] = cur;
}

const int LOG = 18;

int tin[K];
int tout[K];
int up[LOG][K];
int ti;

void dfs(int u, int pp){
    tin[u] = ++ti;
    up[0][u]=pp;
    for(int i = 1; i < LOG; i ++ )
        up[i][u]=up[i-1][up[i-1][u]];
    for(auto x : E[u]){
        dfs(x,u);
    }
    tout[u] = ti;
}

set<int> pos[N];
int L[K];
int v[K];

struct SegTree{
    struct Node{
        int val;
        int lef;
        int rig;
    };
    vector<Node> fs;
    int add_node(){
        int id = fs.size();
        fs.push_back({0,-1,-1});
        return id;
    }
    void upd(int node, int cl, int cr, int pos, int x){
        fs[node].val += x;
        if(cl == cr)
            return ;
        int mid = (cl + cr) >> 1;
        if(mid >= pos){
            if(fs[node].lef == -1){
                int nw = add_node();
                fs[node].lef = nw;
            }
            upd(fs[node].lef, cl, mid, pos, x);
        }
        else{
            if(fs[node].rig == -1){
                int nw = add_node();
                fs[node].rig = nw;
            }
            upd(fs[node].rig, mid + 1, cr, pos, x);
        }
    }
    int get(int node, int cl, int cr, int tl, int tr){
        if(node == -1 || node >= fs.size()) return 0ll;
        if(cr < tl || cl > tr) return 0ll;
        if(cl >= tl && cr <= tr){
            return fs[node].val;
        }
        int mid = (cl + cr) >> 1;
        ll ret = 0ll;
        if(fs[node].lef != -1)ret += get(fs[node].lef, cl, mid, tl, tr);
        if(fs[node].rig != -1)ret += get(fs[node].rig, mid + 1, cr, tl, tr);
        return ret;
    }
};

SegTree nd[K * 4 + 512];

void update(int node, int cl, int cr, int pos, int a, int sign){
    if(nd[node].fs.size() == 0){
        nd[node].add_node();
    }
    nd[node].upd(0, 0, cur, a, sign);
    if(cl == cr) return;
    int mid = (cl + cr) >> 1;
    if(mid >= pos)
        update(node << 1, cl, mid, pos, a, sign);
    else
        update(node << 1 | 1, mid + 1, cr, pos, a, sign);
}

int query(int node, int cl, int cr, int tl, int tr){
    if(cr < tl || cl > tr)
        return 0;
    if(cl >= tl && cr <= tr){
        return nd[node].get(0, 0, cur, 0, tl - 1);
    }
    int mid = (cl + cr) >> 1;
    return query(node << 1, cl, mid, tl, tr) + query(node << 1 | 1, mid + 1, cr, tl, tr);
}

void delet(int id){
    update(1, 0, cur, id, L[id], -1);
    pos[v[id]].erase(id);
    auto it = pos[v[id]].lower_bound(id);
    int ix;
    if(it != pos[v[id]].end()){
        ix = *it;
        update(1, 0, cur, ix, id, -1);
        auto nx = it;
        if(nx != pos[v[id]].begin()){
            nx -- ;
            L[ix] = *nx;
            update(1, 0, cur, ix, *nx, +1);
        }
        else{
            L[ix] = 0;
            update(1, 0, cur, ix, 0, +1);
        }
    }
}

void setpos(int id, int x){
    if(x == v[id])
        return;
    if(v[id] != 0){
        delet(id);
    }
    auto it = pos[x].lower_bound(id);
    int ix;
    if(it != pos[x].end()){
        ix = *it;
        update(1, 0, cur, ix, L[ix],-1);
        update(1, 0, cur, ix, id, +1);
        L[*it] = id;
    }
    if(it != pos[x].begin()){
        it -- ;
        ix = *it;
        update(1, 0, cur, id, ix, +1);
        L[id] = ix;
    }
    else{
        update(1, 0, cur, id, 0, +1);
        L[id] = 0;
    }
    pos[x].insert(id);
    v[id] = x;
}

int main(){
    fastIO;
    int q;
    cin >> n >> m >> q;
    int sz = n * m;
    for(int i = 0 ; i < K; i ++ )
        par[i]=i;
    cur = sz;
    int l;
    vector<pii> cells;
    int ni, nj;
    for(int i = 1; i <= n; i ++ ){
        for(int j = 1; j <= m ; j ++ ){
            cin >> l;
            cells.push_back(mp(l, getid(i, j)));
            for(int k = 0 ; k < 4; k ++ ){
                ni = i + dir[k][0];
                nj = j + dir[k][1];
                if(ni >= 1 && ni <= n && nj >= 1 && nj <= m){
                    T[getid(i,j)].push_back(getid(ni,nj));
                }
            }
        }
    }
    sort(cells.begin(), cells.end());
    for(auto p : cells){
        active[p.se]=true;
        vl[p.se] = p.fi;
        for(auto q : T[p.se]){
            if(active[q]){
                unite(p.se, q);
            }
        }
    }
    dfs(cur, cur);
    int id;
    for(int i = 1; i <= n; i ++ ){
        for(int j = 1; j <= m ; j ++ ){
            cin >> l;
            id = getid(i,j);
            setpos(tin[id], l);
        }
    }
    int typ;
    int xi, yi;
    int cv;
    for(int qr = 0; qr < q; qr ++ ){
        cin >> typ;
        if(typ == 2){
            cin >> yi >> xi >> cv;
            id = getid(xi, yi);
            if(vl[id] > cv){
                cout << 0 << "\n";
            }
            else{
                for(int lg = LOG - 1; lg >= 0; lg -- ){
                    if(vl[up[lg][id]] <= cv){
                        id = up[lg][id];
                    }
                }
                cout << query(1, 0, cur, tin[id], tout[id]) << "\n";
            }
        }
        else{
            cin >> yi >> xi >> cv;
            id = getid(xi, yi);
            setpos(tin[id], cv);
        }
    }
    return 0;
}

Compilation message (stderr)

pokemonmaster.cpp: In member function 'int SegTree::get(int, int, int, int, int)':
pokemonmaster.cpp:106:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<SegTree::Node>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  106 |         if(node == -1 || node >= fs.size()) return 0ll;
      |                          ~~~~~^~~~~~~~~~~~
#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...