제출 #419088

#제출 시각아이디문제언어결과실행 시간메모리
419088pauloamedBridges (APIO19_bridges)C++14
0 / 100
3058 ms13352 KiB
#include<bits/stdc++.h>
using namespace std;

#define MAXN 500010
#define BLOCK 500010

struct DSU{
  int numComponents;
  int sizes[MAXN]; // vetor com tamanhos
  int parents[MAXN]; // vetor com pai de cada no
  stack<pair<int,int>> lastPar, lastSize;
  vector<int> checkpoints;

  DSU(int n){
    lastPar = lastSize = stack<pair<int,int>>();
    checkpoints = {0};
    numComponents = n;
    for(int i = 1; i <= n; ++i){
        sizes[i] = 1; // tamanho inicial
        parents[i] = i; // valor padrao: cada um eh seu pai
    }
  }

  int find(int current){
      int newRoot = current; // variavel para guardar nova raiz
      while(newRoot != parents[newRoot]) // enquanto nao encontro no raiz
          newRoot = parents[newRoot]; // subo na arvore
      return newRoot; // retornamo a raiz da arvore
  }

  void onion(int a, int b){
      a = find(a); b = find(b); // unimos uma raiz a outra

      if(a == b) return; // se for a mesma raiz, nao tenho o que unir

      // uniao por tamanho
      if(sizes[a] < sizes[b]) swap(a,b); // quero unir "b" a "a"

      checkpoints.back()++;
      lastSize.push({a, sizes[a]});
      lastPar.push({b, parents[b]});

      sizes[a] += sizes[b]; // atualizando tamanho de "a"
      parents[b] = a; // pai de "b" eh "a"
      numComponents--;
  }

  void check(){
    checkpoints.push_back(0);
  }

  void rollback(){
    int x = checkpoints.back();
    numComponents += x;
    while (x--) {
      sizes[lastSize.top().first] = lastSize.top().second; lastSize.pop();
      parents[lastPar.top().first] = lastPar.top().second; lastPar.pop();
    }
    checkpoints.pop_back();
  }
};

vector<int> cost = {-1};
vector<pair<int,int>> edges = {{-1, -1}};
vector<pair<int, pair<int,int>>> qs;
/*
first: tipo 1 (update) ou 2 (query)
second:
  tipo 1: first (edge id), second (new weight)
  tipo 2: first (node id), second (cars weight)
*/

vector<pair<int,int>> getSafeEdges(int l, int r, int m){
  set<int> alteredEdges;
  for(int j = l; j <= r; ++j){
    if(qs[j].first == 1){
      int edgeId = qs[j].second.first;
      alteredEdges.insert(edgeId);
    }
  }
  // TODAS ARESTAS ALTERADAS ESTAO EM ALTERED_EDGES

  vector<pair<int,int>> safeEdges;
  for(int j = 1; j <= m; ++j){
    if(alteredEdges.count(j) == 0){
      safeEdges.push_back({cost[j], j});
    }
  }
  // TODAS ARESTAS NAO ALTERADAS ESTAO EM SAFE_EDGES
  // ORDENADAS DECRESCENTE PELO CUSTO
  sort(safeEdges.rbegin(), safeEdges.rend());

  return safeEdges;
}

void updt(int l, int r){
  for(int j = l; j <= r; ++j){
    if(qs[j].first == 1){
      int edgeId = qs[j].second.first;
      int newWeight = qs[j].second.second;
      cost[edgeId] = newWeight;
    }
  }
}


vector<pair<int,int>> getWeightQueries(int l, int r){
  vector<pair<int,int>> weightQueries;
  for(int j = l; j <= r; ++j){
    if(qs[j].first == 2){
      int weight = qs[j].second.second;
      weightQueries.push_back({weight, j});
    }
  }
  sort(weightQueries.rbegin(), weightQueries.rend());
  return weightQueries;
}

int main(){
  iostream::sync_with_stdio(false);
  cin.tie(NULL);

  int n, m; cin >> n >> m;

  for(int i = 0; i < m; ++i){
    int a, b, c; cin >> a >> b >> c;
    cost.push_back(c);
    edges.push_back({a, b});
  }

  int q; cin >> q;
  for(int i = 0; i < q; i++){
    int a, b, c; cin >> a >> b >> c;
    qs.push_back({a, {b, c}});
  }

  vector<int> ans(q, -1);
  for(int i = 0; i < q; i += BLOCK){
    DSU dsu(n);
    int l = i;
    int r = min(q - 1, i + BLOCK - 1);

    //////////////////////////////////////////////////////////////
    // solving range
    auto safeEdges = getSafeEdges(l, r, m);

    // sorting queries
    auto weightQueries = getWeightQueries(l, r);

    int nextSafeEdge = 0;
    for(int j = 0; j < weightQueries.size(); ++j){
      int currWeight = weightQueries[j].first;

      // o carro saindo da cidade atual tem peso menor que ou igual ao peso da proxima
      // edge ainda nao adicionada?
      while(nextSafeEdge < safeEdges.size() && currWeight <= safeEdges[nextSafeEdge].first){
        int edgeId = safeEdges[nextSafeEdge].second;
        int a = edges[edgeId].first;
        int b = edges[edgeId].second;
        dsu.onion(a, b);
        nextSafeEdge++;
      }

      dsu.check();

      // adiciona os updt da range
      // quero adicionar todos os updt do bloco ate chegar em mim
      // e os q passam de mim so q com o peso original
      int currIndex = weightQueries[j].second;
      for(int k = l; k <= r; ++k){
        if(qs[k].first == 1){
          int edgeId = qs[k].second.first;
          int newWeight = qs[k].second.second;
          int w = (k > currIndex? cost[edgeId] : newWeight);

          if(currWeight <= w){
            int a = edges[edgeId].first;
            int b = edges[edgeId].second;
            dsu.onion(a, b);
          }
        }
      }

      int currCity = qs[currIndex].second.first;
      ans[currIndex] = dsu.sizes[dsu.find(currCity)];

      dsu.rollback();
    }


    //////////////////////////////////////////////////////////////
    updt(l, r);
  }

  for(auto x : ans){
    if(x != -1) cout << x << "\n";
  }

}

컴파일 시 표준 에러 (stderr) 메시지

bridges.cpp: In function 'int main()':
bridges.cpp:151:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  151 |     for(int j = 0; j < weightQueries.size(); ++j){
      |                    ~~^~~~~~~~~~~~~~~~~~~~~~
bridges.cpp:156:26: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  156 |       while(nextSafeEdge < safeEdges.size() && currWeight <= safeEdges[nextSafeEdge].first){
      |             ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
#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...