제출 #419155

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

#define MAXN 100010
#define BLOCK 900
int sizes[MAXN]; // vetor com tamanhos
int parents[MAXN]; // vetor com pai de cada no

struct DSU{
  int numComponents;
  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)
*/

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 l = 0; l < q; l += BLOCK){
    DSU dsu(n);
    int r = min(q - 1, l + BLOCK - 1);

    //////////////////////////////////////////////////////////////

    // TODAS ARESTAS ALTERADAS ESTAO EM ALTERED_EDGES

    vector<pair<int,int>> safeEdges;
    vector<pair<int,int>> weightQueries;
    vector<int> unsafeQueries, unsafeEdges;

    // solving range
    vector<int> alteredEdges(m + 1);
    for(int i = l; i <= r; ++i){
      if(qs[i].first == 1){
        int edgeId = qs[i].second.first;
        alteredEdges[edgeId] = 1;
        unsafeQueries.push_back(i);
        unsafeEdges.push_back(edgeId);
      }else{
        int weight = qs[i].second.second;
        weightQueries.push_back({weight, i});
      }
    }

    for(int i = 1; i <= m; ++i){
      if(alteredEdges[i] == 0){
        safeEdges.push_back({cost[i], i});
      }
    }
    // TODAS ARESTAS NAO ALTERADAS ESTAO EM SAFE_EDGES
    // ORDENADAS DECRESCENTE PELO CUSTO


    sort(weightQueries.rbegin(), weightQueries.rend());
    sort(safeEdges.rbegin(), safeEdges.rend());

    sort(unsafeEdges.begin(), unsafeEdges.end());
    unsafeEdges.resize(unique(unsafeEdges.begin(), unsafeEdges.end()) - unsafeEdges.begin());

    int nextSafeEdge = 0;
    for(int i = 0; i < weightQueries.size(); ++i){
      int currWeight = weightQueries[i].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;
        dsu.onion(edges[edgeId].first, edges[edgeId].second);
        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[i].second;
      int currCity = qs[currIndex].second.first;


      for(auto x : unsafeEdges) alteredEdges[x] = 0;
      for(int j = 0; j < unsafeQueries.size(); j++){
        int k = unsafeQueries[j];
        int edgeId = qs[k].second.first;
        if(k > currIndex){
          if(alteredEdges[edgeId] == 0) alteredEdges[edgeId] = cost[edgeId];
        }else{
          int newWeight = qs[k].second.second;
          alteredEdges[edgeId] = newWeight;
        }
      }

      for(auto x : unsafeEdges){
        if(currWeight <= alteredEdges[x]){
          dsu.onion(edges[x].first, edges[x].second);
        }
      }

      ans[currIndex] = sizes[dsu.find(currCity)];
      dsu.rollback();
    }

    for(int j = 0; j < unsafeQueries.size(); j++){
      int k = unsafeQueries[j];
      int edgeId = qs[k].second.first;
      int newWeight = qs[k].second.second;
      cost[edgeId] = newWeight;
    }
  }

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

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

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