Submission #1117250

#TimeUsernameProblemLanguageResultExecution timeMemory
1117250Mike_VuBridges (APIO19_bridges)C++14
100 / 100
1476 ms11372 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double dou;
#define pii pair<int, int>
#define fi first
#define se second
#define pb push_back
#define MASK(x) (1LL<<(x))
#define BITj(x, j) (((x)>>(j))&1)
#define ALL(v) (v).begin(), (v).end()
 
template<typename T> bool maximize(T &x, const T &y) {
    if (x < y) {x = y; return 1;}
    return 0;
}
template<typename T> bool minimize(T &x, const T &y) {
    if (x > y) {x = y; return 1;}
    return 0;
}
 
struct DSU{
    int n;
    vector<int> dsu;
    void init(int _n = 0) {
        n = _n;
        dsu.assign(n+1, -1);
    }
    int f(int u) {
        return dsu[u] < 0 ? u : dsu[u] = f(dsu[u]);
    }
    int sz(int u) {
        return -dsu[f(u)];
    }
    bool join(int u, int v) {
        u = f(u);
        v = f(v);
        if (u == v) return 0;
        if (dsu[u] > dsu[v]) swap(u, v);
        dsu[u] += dsu[v];
        dsu[v] = u;
        return 1;
    }
};
 
struct query{
    int u, w, ans;
    bool type;
    query(bool _type, int _u, int _w) {
        type = _type;
        u = _u;
        w = _w;
    }
};
 
const int maxn = 5e4+5, maxm = 1e5+5, B = 800;///B = 200
int n, m, q;
vector<pii> edges; ///edges
vector<int> curw; ///current weight
vector<query> qu;
DSU dsu;
 
namespace sub1{
    bool check() {
        return (min(n, m) <= 1005 && q <= 10005);
    }
    void solve() {
        //for every query -> build dsu from scratch
        for (int i = 0; i < q; i++) {
            if (qu[i].type == 0) {
                //update
                curw[qu[i].u] = qu[i].w;
 
            }
            else {
                dsu.init(n);
                for (int id = 0; id < m; id++) {
                    if (curw[id] >= qu[i].w) {
                        dsu.join(edges[id].fi, edges[id].se);
                    }
                }
                cout << dsu.sz(qu[i].u) << "\n";
            }
        }
    }
}
 
namespace sub6{
    bool cmpedgeid1(const int &a, const int &b) {
        if (curw[a] != curw[b]) return curw[a] > curw[b];
        return a < b;
    }
    bool cmpqub(pii a, pii b){
        if (qu[a.fi].w != qu[b.fi].w) return qu[a.fi].w > qu[b.fi].w;
        return a.se < b.se;
    }
    multiset<int, bool (*) (const int &, const int &)> st(cmpedgeid1);
    vector<int> adj[maxn], curup, tempw, curedges;
    vector<pii> curqu;
    bool vis[maxn];
    int curans;
    void dfs(int u) {
        vis[u] = 1;
        curans += dsu.sz(u);
        for (int v : adj[u]) {
            if (!vis[v]) {
                dfs(v);
            }
        }
    }
    void solveblock(int ql, int qr) {
        //remove edges inside this block in set
        int sumt = 0;
        for (int i = ql; i <= qr; i++) {
            if (qu[i].type == 0) {
                //update
                int u = qu[i].u;
                auto it = st.find(u);
                if (it != st.end()) st.erase(it);
                curup.pb(i);
                curedges.pb(u);
                ++sumt;
            }
            else {
                curqu.pb({i, sumt});
            }
        }
        //discretize edges
        sort(ALL(curedges));
        curedges.erase(unique(ALL(curedges)), curedges.end());
        //check for weights
        //sort nodes' weights descendingly
        sort(ALL(curqu), cmpqub);
        dsu.init(n);
        auto allit = st.begin();
        //for each query
        for (pii e : curqu) {
            int quid = e.fi, start = qu[quid].u, bound = qu[quid].w, curt = e.se;
//            cout << quid << ' ' << curt << "\n";
            //DSU
            while (allit != st.end() && curw[(*allit)] >= bound) {
                dsu.join(edges[(*allit)].fi, edges[(*allit)].se);
                ++allit;
            }
            //update weight
            for (int t = 0; t < curt; t++) {
                int id = curup[t];
                tempw[qu[id].u] = qu[id].w;
            }
            //build graph
            for (int id : curedges){
                if (tempw[id] < bound) continue;
                int u = edges[id].fi, v = edges[id].se;
                u = dsu.f(u);
                v = dsu.f(v);
                if (u == v) continue;
                adj[u].pb(v);
                adj[v].pb(u);
            }
            //dfs count
            curans = 0;
            int startreal = dsu.f(start);
            dfs(startreal);
            qu[quid].ans = curans;
            //clear adj, tempw, vis
            vis[startreal] = 0;
            for (int id : curedges){
                tempw[id] = curw[id];
                int u = edges[id].fi, v = edges[id].se;
                u = dsu.f(u);
                v = dsu.f(v);
                if (u == v) continue;
                adj[u].clear();
                adj[v].clear();
                vis[u] = vis[v] = 0;
            }
        }
        //after this block -> update set, curw
        for (int id : curup) {
            curw[qu[id].u] = qu[id].w;
        }
        //set
        for (int id : curedges) {
            tempw[id] = curw[id];
            st.insert(id);
        }
        //clear
        curup.clear();
        curedges.clear();
        curqu.clear();
    }
    void solve() {
        //prepare list of edges in descending order -> set
        //init part
        for (int i = 0; i < m; i++) {
            st.insert(i);
            tempw.pb(curw[i]); //save the temp weight -> undo
        }
        memset(vis, 0, sizeof(vis));
        //for every B queries
        for (int numb = 0; numb*B < q; numb++) {
            solveblock(numb*B, min(numb*B+B-1, q-1));
        }
        //output
        for (int i = 0; i < q; i++) {
            if (qu[i].type) {
                cout << qu[i].ans << "\n";
            }
        }
    }
}
 
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
//    #define name "task"
//    if (fopen(name".inp", "r")) {
//        freopen(name".inp", "r", stdin);
//        freopen(name".out", "w", stdout);
//    }
    //input
    cin >> n >> m;
    for (int i= 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        edges.pb({u, v});
        curw.pb(w);
    }
    cin >> q;
    for (int i = 0; i < q; i++) {
        int t, u, w;
        cin >> t >> u >> w;
        qu.pb(query(t==2, t == 1 ? u-1 : u, w));
    }
//    if (sub1::check()) return sub1::solve(), 0;
    return sub6::solve(), 0;
}
#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...