제출 #1333723

#제출 시각아이디문제언어결과실행 시간메모리
1333723YSH2020Wind Turbines (EGOI25_windturbines)C++20
54 / 100
4094 ms74632 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 = 325;
bool comp2(pair<pair<int, int>,int> a, pair<pair<int, int>,int> b) {
    int blocknum1 = a.first.first/block_size;
    int blocknum2 = b.first.first/block_size;
    if (blocknum1 != blocknum2) return blocknum1 < blocknum2;
    if (blocknum1%2==0) return a.first.second < b.first.second;
    else return b.first.second > a.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<pair<int,int>> curorders;
int totalweight = 0;
int tmp;

signed main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    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++;
        }
    }
    tmp = totalweight;
    //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, y}, i};
    }
    sort(q_vect.begin(), q_vect.end(), comp2);
    for (auto q:q_vect) {
        while (cur_l > q.first.first) {
            cur_l--;
            int n = cur_l;
    if (curorders.size() == 0) {curorders.insert({preord[n],0});}
    else {
        auto itr = curorders.lower_bound({preord[n],0});
        if (itr == curorders.end()) {
            //its right most
            itr--;
            totalweight -= weights[lca((*itr).second, n)];
        }
        else if (itr == curorders.begin()) {
            totalweight -= weights[lca((*itr).second, n)];
        }
        else {
            int r = (*itr).second;
            itr--;
            int l = (*itr).second;
            totalweight -= weights[lca(l,n)];
            totalweight -= weights[lca(r,n)];
            totalweight += weights[lca(l,r)];
        }
        curorders.insert({preord[n],n});
    }
        }
        while (cur_r < q.first.second) {
            cur_r++;
            int n = cur_r;
                if (curorders.size() == 0) {curorders.insert({preord[n],0});}
    else {
        auto itr = curorders.lower_bound({preord[n],0});
        if (itr == curorders.end()) {
            //its right most
            itr--;
            totalweight -= weights[lca((*itr).second, n)];
        }
        else if (itr == curorders.begin()) {
            totalweight -= weights[lca((*itr).second, n)];
        }
        else {
            int r = (*itr).second;
            itr--;
            int l = (*itr).second;
            totalweight -= weights[lca(l,n)];
            totalweight -= weights[lca(r,n)];
            totalweight += weights[lca(l,r)];
        }
        curorders.insert({preord[n],n});
    }
        }
        while (cur_l < q.first.first) {
            int n = cur_l;
                curorders.erase(curorders.find({preord[n],n}));
    if (curorders.size()==0);
    else if (curorders.size()==1) {totalweight = tmp;}
    else {
        auto itr = curorders.lower_bound({preord[n],0});
        if (itr == curorders.end()) {
            //its right most
            itr--;
            totalweight += weights[lca((*itr).second, n)];
        }
        else if (itr == curorders.begin()) {
            totalweight += weights[lca((*itr).second, n)];
        }
        else {
            int r = (*itr).second;
            itr--;
            int l = (*itr).second;
            totalweight += weights[lca(l,n)];
            totalweight += weights[lca(r,n)];
            totalweight -= weights[lca(l,r)];
        }
    }
            cur_l++;

        }
        while (cur_r > q.first.second) {
            int n = cur_r;
    curorders.erase(curorders.find({preord[n],n}));
    if (curorders.size()==0);
    else if (curorders.size()==1) {totalweight = tmp;}
    else {
        auto itr = curorders.lower_bound({preord[n],0});
        if (itr == curorders.end()) {
            //its right most
            itr--;
            totalweight += weights[lca((*itr).second, n)];
        }
        else if (itr == curorders.begin()) {
            totalweight += weights[lca((*itr).second, n)];
        }
        else {
            int r = (*itr).second;
            itr--;
            int l = (*itr).second;
            totalweight += weights[lca(l,n)];
            totalweight += weights[lca(r,n)];
            totalweight -= weights[lca(l,r)];
        }
    }
            cur_r--;

        }
        ans[q.second] = totalweight;
    }
    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...