Submission #1297801

#TimeUsernameProblemLanguageResultExecution timeMemory
1297801danglayloi1Collapse (JOI18_collapse)C++20
0 / 100
169 ms6320 KiB
#include "collapse.h"
#include<bits/stdc++.h>
using namespace std;

#define foru(i,a,b) for(int i=(a); i<=(b); ++i)
#define ford(i,a,b) for(int i=(a); i>=(b); --i)
#define rep(i,a) for(int i=0; i<(a); ++i)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define ii pair<int,int>
#define vi vector<int>
#define vii vector<ii>
#define fi first
#define se second
#define ll long long
#define eb emplace_back
#define pb push_back

const int B=300;
const int N=1e5+5;

int n,c,q;
vi del;
map<ii,int> mp;
vector<int> ed[N],red[N],que[N],exEd;

struct DSU{
    int par[N], sz[N];
    // safe history: (type, index, old_value)
    // type 0 -> par[idx] old value
    // type 1 -> sz[idx] old value
    vector<tuple<int,int,int>> history;

    DSU(){
        memset(par,0,sizeof(par));
        memset(sz,0,sizeof(sz));
        history.clear();
    }
    void init(int n){
        history.clear();
        iota(par, par+n, 0);
        fill(sz, sz+n, 1);
    }
    int find(int x){
        return par[x]==x ? x : par[x]=find(par[x]);
    }
    bool unite(int x, int y){
        x=find(x); y=find(y);
        if(x==y) return false;
        if(sz[x]<sz[y]) swap(x,y);
        history.emplace_back(0, y, par[y]);
        history.emplace_back(1, x, sz[x]);
        par[y]=x;
        sz[x]+=sz[y];
        return true;
    }
    int snapshot(){ return (int)history.size(); }
    void rollback(int x){
        while((int)history.size()>x){
            auto [type, idx, old] = history.back(); history.pop_back();
            if(type==0) par[idx]=old; else sz[idx]=old;
        }
    }
} dsu;

vi simulateCollapse(int nn, vi tt, vi xx, vi yy, vi ww, vi pp){
    n=nn; c=sz(tt); q=sz(ww);

    del.assign(c, c);
    mp.clear();

    // Normalize vertex indices to 0-based if they appear 1-based
    bool one_based_vertices=false;
    rep(i,c) if(xx[i]==n || yy[i]==n) { one_based_vertices=true; break; }
    if(one_based_vertices) rep(i,c){ xx[i]--; yy[i]--; }

    // Normalize pp (positions) to 0-based if needed
    bool one_based_pos=false;
    rep(i,q) if(pp[i]==n) { one_based_pos=true; break; }
    if(one_based_pos) rep(i,q) pp[i]--;

    rep(i,c){
        if(xx[i]>yy[i]) swap(xx[i], yy[i]);
        if(tt[i]==0){ // add
            mp[{xx[i], yy[i]}]=i;
        } else { // delete
            auto it = mp.find({xx[i], yy[i]});
            if(it!=mp.end()) del[it->second]=i;
            else {
                // unmatched delete - ignore defensively
            }
        }
    }

    vi id(q), ans(q,0);
    iota(all(id), 0);
    sort(all(id), [&](int a, int b){ return ww[a] < ww[b]; });

    int l=0, lq=0;
    while(l<c){
        int r=min(c-1, l+B);
        // clear buckets
        rep(i,n){ que[i].clear(); ed[i].clear(); red[i].clear(); }
        exEd.clear();

        // prepare queries whose position p <= r
        while(lq<q && ww[id[lq]]<=r){
            if(pp[id[lq]]>=0 && pp[id[lq]]<n) que[pp[id[lq]]].eb(id[lq]);
            ++lq;
        }

        // prepare edges added before block
        rep(i,l) if(tt[i]==0){
            if(del[i]>=l){
                if(del[i]>r){
                    ed[yy[i]].eb(i);
                    red[xx[i]].eb(i);
                } else {
                    exEd.eb(i);
                }
            }
        }

        // forward sweep
        int cc=0;
        dsu.init(n);
        rep(i,n){
            ++cc;
            for(int j: ed[i]) if(dsu.unite(xx[j], yy[j])) --cc;
            for(int j: que[i]){
                int tmp = dsu.snapshot();
                int cnt = 0;
                rep(k, (int)exEd.size()){
                    int ide = exEd[k];
                    if(yy[ide] <= i && del[ide] > ww[j]){
                        if(dsu.unite(xx[ide], yy[ide])) { --cc; ++cnt; }
                    }
                }
                foru(k, l, ww[j]){
                    if(tt[k]==0 && yy[k] <= i && del[k] > ww[j]){
                        if(dsu.unite(xx[k], yy[k])) { --cc; ++cnt; }
                    }
                }
                ans[j] += cc;
                cc += cnt;
                dsu.rollback(tmp);
            }
        }

        // backward sweep
        cc = 0;
        dsu.init(n);
        ford(i, n-1, 1){
            ++cc;
            for(int j: red[i]) if(dsu.unite(xx[j], yy[j])) --cc;
            for(int j: que[i-1]){
                int tmp = dsu.snapshot();
                int cnt = 0;
                rep(k, (int)exEd.size()){
                    int ide = exEd[k];
                    if(xx[ide] >= i && del[ide] > ww[j]){
                        if(dsu.unite(xx[ide], yy[ide])) { --cc; ++cnt; }
                    }
                }
                foru(k, l, ww[j]){
                    if(tt[k]==0 && xx[k] >= i && del[k] > ww[j]){
                        if(dsu.unite(xx[k], yy[k])) { --cc; ++cnt; }
                    }
                }
                ans[j] += cc;
                cc += cnt;
                dsu.rollback(tmp);
            }
        }

        l = r + 1;
    }

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