제출 #1327271

#제출 시각아이디문제언어결과실행 시간메모리
1327271nguyenkhangninh99I want to be the very best too! (NOI17_pokemonmaster)C++20
100 / 100
351 ms45632 KiB

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 5;
int a[maxn], b[maxn], flat[maxn], par[maxn], bit[maxn], ans[maxn];
int up[maxn][16], tin[maxn], out[maxn], timedfs;
vector<int> adj[maxn];
set<int> pos[maxn]; 

int find(int u){
    return par[u] == u ? u : par[u] = find(par[u]);
}
void dfs(int u){
    tin[u] = ++timedfs;
    flat[tin[u]] = b[u]; 
    for(int v: adj[u]){
        up[v][0] = u;
        for(int j = 1; j <= 15; j++) up[v][j] = up[up[v][j - 1]][j - 1];
        dfs(v);
    }
    out[u] = timedfs;
}
void update(int p, int v){
    for (; p < maxn; p += p &- p) bit[p] += v;
}
int get(int p){
    int res = 0;
    for(; p; p -= p & -p) res += bit[p];
    return res;
}
struct node{
    int x, y, val, type, id;
};
vector<node> qry, mergesort;
void addpoint(int x, int y, int val){
    qry.push_back({x, y + 1, val, 1, 0});
}
void addquery(int x, int y, int sign, int id){
    qry.push_back({x, y + 1, sign, 2, id});
}
void cdq(int l, int r){
    if(l >= r) return;
    int mid = (l + r) / 2;
    cdq(l, mid);
    cdq(mid + 1, r);

    int i = l, j = mid + 1, k = l;
    while(i <= mid && j <= r){
        if(qry[i].x <= qry[j].x){
            if(qry[i].type == 1) update(qry[i].y, qry[i].val);
            mergesort[k++] = qry[i++];
        }else{
            if(qry[j].type == 2) ans[qry[j].id] += qry[j].val * get(qry[j].y);
            mergesort[k++] = qry[j++];
        }
    }
    while(j <= r){
        if(qry[j].type == 2) ans[qry[j].id] += qry[j].val * get(qry[j].y);
        mergesort[k++] = qry[j++];
    }
    for(int p = l; p < i; p++){
        if(qry[p].type == 1) update(qry[p].y, -qry[p].val);
    }
    while(i <= mid) mergesort[k++] = qry[i++];
    for(int p = l; p <= r; p++) qry[p] = mergesort[p];
}

signed main(){
    ios_base::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    
    int r, c, q; cin >> r >> c >> q;

    vector<array<int, 3>> val;
    for(int i = 1; i <= r; i++){
        for(int j = 1; j <= c; j++){
            cin >> a[(i - 1) * c + j];
            val.push_back({a[(i - 1) * c + j], i, j});
        }
    }

    for(int i = 1; i <= r; i++){
        for(int j = 1; j <= c; j++) cin >> b[(i - 1) * c + j];
    }

    sort(val.begin(), val.end());
    for(int i = 1; i <= r * c; i++) par[i] = i;

    array<pair<int, int>, 4> d = array<pair<int, int>, 4>{pair<int, int>{-1, 0}, pair<int, int>{1, 0}, pair<int, int>{0, 1}, pair<int, int>{0, -1}};
    for(auto [_, x, y]: val){
        int u = (x - 1) * c + y;
        for(auto [dx, dy]: d){
            int nx = x + dx, ny = y + dy;
            if(nx < 1 || ny < 1 || nx > r || ny > c) continue;
            int v = (nx - 1) * c + ny;
            if(a[v] > a[u]) continue;
            v = find(v);
            par[v] = u;
            if(v != u) adj[u].push_back(v);
        }
    }
    int root = (val.back()[1] - 1) * c + val.back()[2];
    for(int j = 0; j <= 15; j++) up[root][j] = root;
    dfs(root);

    for(int i = 1; i <= r * c; i++) pos[flat[i]].insert(i);

    for(int i = 1; i <= 50000; i++){
        int last = 0;
        for(auto p: pos[i]){
            addpoint(p, last, 1); //last = pre[i];
            last = p;
        }
    }

    int cnt = 0;
    for(int i = 1; i <= q; i++){
        int type, x, y, k; cin >> type >> y >> x >> k;
        if(type == 1){
            int u = (x - 1) * c + y, old = flat[tin[u]];

            auto it = pos[old].find(tin[u]);
            int pre = 0, nxt = 0;
            if(it != pos[old].begin()) pre = *prev(it);
            if(next(it) != pos[old].end()) nxt = *next(it);
            pos[old].erase(it);
            
            addpoint(tin[u], pre, -1); //xóa điểm (tin[u], pre)
            if(nxt){
                addpoint(nxt, tin[u], -1); //nếu có nxt xóa (nxt, tin[u]);
                addpoint(nxt, pre, 1); //thêm điểm (nxt, pre)
            }

            pos[k].insert(tin[u]);
            it = pos[k].find(tin[u]);
            pre = 0; nxt = 0;
            if(it != pos[k].begin()) pre = *prev(it);
            if(next(it) != pos[k].end()) nxt = *next(it);

            addpoint(tin[u], pre, 1);
            if(nxt){
                addpoint(nxt, tin[u], 1);
                addpoint(nxt, pre, -1);
            }
            flat[tin[u]] = k;
        }else{
            int u = (x - 1) * c + y;
            cnt++;
            if(a[u] > k) continue; 
        
            for(int j = 15; j >= 0; j--){
                if(a[up[u][j]] <= k) u = up[u][j];
            }
            int l = tin[u], r = out[u];
            addquery(r, l - 1, 1, cnt);
            addquery(l - 1, l - 1, -1, cnt);
        }
    }

    mergesort.resize(qry.size());
    cdq(0, qry.size() - 1);
    for (int i = 1; i <= cnt; i++) cout << ans[i] << "\n";
}
#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...