Submission #1127597

#TimeUsernameProblemLanguageResultExecution timeMemory
1127597InvMOD다리 (APIO19_bridges)C++20
14 / 100
1754 ms8564 KiB
#include <bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define gcd __gcd
#define sz(v) (int) v.size()
#define pb push_back
#define pi pair<int,int>
#define all(v) (v).begin(), (v).end()
#define compact(v) (v).erase(unique(all(v)), (v).end())
#define FOR(i, a, b) for(int i = (a); i <= (b); i++)
#define REV(i, a, b) for(int i = (a); i >= (b); i--)
#define dbg(x) "[" #x " = " << (x) << "]"
///#define int long long

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template<typename T> bool ckmx(T& a, const T& b){if(a < b) return a = b, true; return false;}
template<typename T> bool ckmn(T& a, const T& b){if(a > b) return a = b, true; return false;}

struct DSU{
    vector<int> par,sz;
    vector<pair<int&, int>> state;

    DSU(int n = 0): par(n + 1) {
        sz.resize(n + 1);
        for(int i = 1; i <= n; i++){
            par[i] = i;
            sz[i] = 1;
        }
        return;
    }

    int f(int x){
        return x == par[x] ? x : f(par[x]);
    }

    bool join(int u, int v){
        u = f(u), v = f(v);

        if(u == v) return false;
        if(sz[u] < sz[v]) swap(u, v);

        state.pb({sz[u], sz[u]});
        state.pb({par[v], par[v]});

        par[v] = u;
        sz[u] += sz[v];
        return true;
    }

    int snap(){
        return sz(state);
    }

    int gsz(int x){
        return sz[f(x)];
    }

    void rollback(int time){
        while(snap() > time){
            assert(sz(state) > 0);
            state.back().fi = state.back().se;
            state.pop_back();
        }
        return;
    }
};

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

struct Edge{
    int u,v,w;
    Edge(int u = 0, int v = 0, int w = 0): u(u), v(v), w(w) {}

    bool operator < (const Edge& q) const{
        return (w == q.w ? (v > q.v) : (w > q.w));
    }
};

struct Query{
    int op,v,w;
    Query(int op = 0, int v = 0, int w = 0): op(op), v(v), w(w) {}
};

int n, m, q, answer[N];

int nxtQ[N];

bool inBlock[N], changeUpd[N];

Edge E[N]; Query Q[N];


void solveBlock(int idBlock){
    int lBlock = (idBlock - 1) * B + 1;
    int rBlock = min(q, idBlock * B);

    vector<Edge> Eblock; vector<int> saveUpd, saveEdge;
    for(int i = lBlock; i <= rBlock; i++){
        if(Q[i].op & 1){
            saveUpd.push_back(i);
            inBlock[Q[i].v] = true;
        }
        else{
            Eblock.push_back(Edge(i, -1, Q[i].w));
        }
    }

    for(int i = 1; i <= m; i++){
        if(!inBlock[i]) Eblock.push_back(E[i]);
        else{
            saveEdge.push_back(i);
        }
    }

    sort(all(Eblock));

    DSU dsu(n);

    for(int i = 0; i < sz(Eblock); i++){
        if(Eblock[i].v == -1){
            // Query
            int cur_Qid = Eblock[i].u, snap = dsu.snap();

            for(int j = 0; j < sz(saveUpd); j++){
                int id = saveUpd[j];
                if(id <= cur_Qid && nxtQ[id] > cur_Qid){
                    int idEdge = Q[id].v;

                    if(!changeUpd[idEdge]){
                        changeUpd[idEdge] = true;
                    }

                    if(Q[id].w >= Q[cur_Qid].w){
                        int u = E[idEdge].u, v = E[idEdge].v;
                        dsu.join(u, v);
                    }
                }
            }

            for(int j = 0; j < sz(saveEdge); j++){
                if(!changeUpd[saveEdge[j]]){
                    if(E[saveEdge[j]].w >= Q[cur_Qid].w){
                        int u = E[saveEdge[j]].u;
                        int v = E[saveEdge[j]].v;
                        dsu.join(u, v);
                    }
                }
                else changeUpd[saveEdge[j]] = false;
            }

            answer[cur_Qid] = dsu.gsz(Q[cur_Qid].v);
            dsu.rollback(snap);
        }
        else{
            // Normal Update
            int u = Eblock[i].u, v = Eblock[i].v;
            dsu.join(u, v);
        }
    }

    for(int i = lBlock; i <= rBlock; i++){
        int idEdge = Q[i].v;
        if(Q[i].op & 1){
            E[idEdge].w = Q[i].w;
            inBlock[idEdge] = false;
        }
    }
    return;
}

void preprocess()
{
    vector<int> nxt(m + 1, q + 1);
    for(int i = 1; i <= q; i++){
        if(Q[i].op & 1){
            int id = Q[i].v;
            nxtQ[i] = nxt[id];
            nxt[id] = i;
        }
    }
    return;
}

void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int u,v,w; cin >> u >> v >> w;
        E[i] = Edge(u, v, w);
    }

    cin >> q;
    for(int i = 1; i <= q; ++i){
        int op,id,w;
        cin >> op >> id >> w;
        Q[i] = Query(op, id, w);
    }
    preprocess();

    int qblock = (q + B - 1) / B;
    for(int i = 1; i <= qblock; i++){
        solveBlock(i);
    }

    for(int i = 1; i <= q; i++){
        if(Q[i].op % 2 == 0) cout << answer[i] << "\n";
    }
    return;
}

signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    #define name "InvMOD"
    if(fopen(name".INP", "r")){
        freopen(name".INP","r",stdin);
        freopen(name".OUT","w",stdout);
    }

    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

Compilation message (stderr)

bridges.cpp: In function 'int main()':
bridges.cpp:225:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  225 |         freopen(name".INP","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
bridges.cpp:226:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  226 |         freopen(name".OUT","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...