제출 #1333692

#제출 시각아이디문제언어결과실행 시간메모리
1333692YSH2020Wind Turbines (EGOI25_windturbines)C++20
0 / 100
4096 ms69884 KiB
//we attempt coding lca on kruskal tree for the first time. lets hope it goes ok

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



#define int long long
const int MAXN=100005;
int block_size = 305;
bool comp2(pair<pair<int, int>,int> a, pair<pair<int, int>,int> b) {
    return make_pair(a.first.first / block_size, a.first.second) < make_pair(b.first.first / block_size, b.first.second);
};


struct ufds{
    int par[2*MAXN];
    ufds(int n) {
        for (int i= 0; i < n; i++) par[i]=i;
    }
    int getp(int x) {
        if (par[x]==x) return x;
        else return par[x]=getp(par[x]);
    }
    int join(int x, int y) {
        x = getp(x);
        y = getp(y);
        if (x==y) return 0;
        par[x]=y;
        return 1;
    }
};

vector<int> adj[2*MAXN];
int depth[2*MAXN];
int par[2*MAXN][22];
int preord[2*MAXN];
int weights[2*MAXN];
int ord = 0;
void dfs(int n, int p) {
    par[n][0]=p;
    preord[n]=ord;
    ord++;
    for (auto i:adj[n]) {
        if (i!=p) {
            depth[i]=depth[n]+1;
            dfs(i,n);
        }
    }
}
void build(int N) {
    for (int i = 1; i < 22; i++) {
        for (int j = 0; j < N; j++) {
            par[j][i]=par[par[j][i-1]][i-1];
        }
    }
}

int kpar(int n, int k) {
    for (int i = 0; i < 22; i++) {
        if (k&(1<<i)) n = par[n][i];
    }
    return n;
}

int lca(int x, int y) {
    if (depth[x] < depth[y]) swap(x,y);
    x = kpar(x,depth[x]-depth[y]);
    if (x==y) return x;
    for (int i = 21; i >= 0; i--) {
        if (par[x][i]!=par[y][i]) {
            x = par[x][i];
            y = par[y][i];
        }
    }
    
    return par[x][0];
}

bool comp(int x, int y) {
    return preord[x] < preord[y];
}

set<int> curorders;
int totalweight = 0;

void add(int n) {
    if (curorders.size() == 0) {curorders.insert(preord[n]);return;}
    auto itr = curorders.lower_bound(preord[n]);
    if (itr == curorders.end()) {
        //its right most
        itr--;
        totalweight -= weights[lca(*itr, preord[n])];
    }
    else if (itr == curorders.begin()) {
        totalweight -= weights[lca(*itr, preord[n])];
    }
    else {
        int r = *itr;
        itr--;
        int l = *itr;
        totalweight -= weights[lca(l,preord[n])];
        totalweight -= weights[lca(r,preord[n])];
        totalweight += weights[lca(l,r)];
    }
    curorders.insert(preord[n]);
}
void remove(int n) {
    curorders.erase(curorders.find(preord[n]));
    if (curorders.size()==0) return;
    auto itr = curorders.lower_bound(preord[n]);
    if (itr == curorders.end()) {
        //its right most
        itr--;
        totalweight += weights[lca(*itr, preord[n])];
    }
    else if (itr == curorders.begin()) {
        totalweight += weights[lca(*itr, preord[n])];
    }
    else {
        int r = *itr;
        itr--;
        int l = *itr;
        totalweight += weights[lca(l,preord[n])];
        totalweight += weights[lca(r,preord[n])];
        totalweight -= weights[lca(l,r)];
    }
}
void remove(int n);
int query() {
    return totalweight;
}


signed main() {
    int n,m,q; cin >> n >> m >> q;
    vector<pair<int,pair<int,int>>> edges(m);
    for (int i = 0; i < m; i++) {
        int a,b,c; cin >> a >> b >> c; edges[i]={c,{a,b}};
    }
    sort(edges.begin(), edges.end());
    ufds *root1 = new ufds(n);
    ufds *root2 = new ufds(2*n);
    int idx = n;
    for (int i = 0; i < m; i++) {
        int w = edges[i].first;
        int a = edges[i].second.first;
        int b = edges[i].second.second;
        if (root1->join(a,b)) {
            //you can join!
            totalweight += w;
            int kroot1 = root2->getp(a);
            int kroot2 = root2->getp(b);
            adj[kroot1].push_back(idx);
            adj[kroot2].push_back(idx);
            adj[idx].push_back(kroot2);
            adj[idx].push_back(kroot1);
            root2->join(a,idx);
            root2->join(b,idx);
            weights[idx]=w;
            idx++;
        }
    }
    //now you have the kruskal tree built. notice that the root is now going to be idx-1;
    idx--;
    depth[idx]=0;
    dfs(idx,idx);
    build(idx+1);
    //
    int cur_l = 0;
    int cur_r = -1;
    vector<pair<pair<int,int>,int>> q_vect(q);
    int ans[q];
    for (int i = 0; i < q; i++) {
        int x, y; cin >> x >> y;
        q_vect[i] = {{x-1, y-1}, i};
    }
    sort(q_vect.begin(), q_vect.end(), comp2);
    for (auto q:q_vect) {
        while (cur_l > q.first.first) {
            cur_l--;
            add(cur_l);
        }
        while (cur_r < q.first.second) {
            cur_r++;
            add(cur_r);
        }
        while (cur_l < q.first.first) {
            remove(cur_l);
            cur_l++;
        }
        while (cur_r > q.first.second) {
            remove(cur_r);
            cur_r--;
        }
        ans[q.second] = query();
    }
    for (int i = 0; i < q; 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...