제출 #1364104

#제출 시각아이디문제언어결과실행 시간메모리
1364104TraianDanciu열대 식물원 (Tropical Garden) (IOI11_garden)C++20
100 / 100
49 ms22764 KiB
#include "gardenlib.h"
#include "garden.h"
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

const int MAXN = 150000;

int best[MAXN], best2[MAXN], nxt[2 * MAXN], ans[2 * MAXN + 1], viz[2 * MAXN], ciclu[2 * MAXN], oncycle[2 * MAXN];
int depth[2 * MAXN], tin[2 * MAXN], tout[2 * MAXN], timer, root[2 * MAXN], cyclepoz[2 * MAXN], cyclesz[2 * MAXN];
int ord[MAXN], answers[MAXN], freq[2][2 * MAXN + 1];
vector<int> g[2 * MAXN], upd[2];

void dfs(int node) {
  tin[node] = ++timer;
  for(int son : g[node]) {
    depth[son] = 1 + depth[node];
    root[son] = root[node];
    dfs(son);
  }
  tout[node] = timer;
}

void solve(int node, int target, int which) {
  if(ciclu[node] != ciclu[target]) {
    return;
  }
  if(!oncycle[target]) {
    if(tin[target] <= tin[node] && tout[node] <= tout[target]) {
      ans[depth[node] - depth[target]]++;
    }
    return;
  }
  int cnt = depth[node];
  node = root[node];
  if(cyclepoz[node] <= cyclepoz[target]) {
    cnt += cyclepoz[target] - cyclepoz[node];
  } else {
    cnt += cyclesz[ciclu[node]] - cyclepoz[node] + cyclepoz[target];
  }
  upd[which].push_back(cnt);
}

void count_routes(int n, int m, int p, int r[][2], int q, int qval[]) {
  for(int i = 0; i < n; i++) {
    best[i] = best2[i] = -1;
  }
  for(int i = m - 1; i >= 0; i--) {
    best2[r[i][0]] = best[r[i][0]];
    best[r[i][0]] = r[i][1];
    best2[r[i][1]] = best[r[i][1]];
    best[r[i][1]] = r[i][0];
  }
  for(int i = 0; i < n; i++) {
    if(best2[i] == -1) {
      best2[i] = best[i];
    }
  }
  for(int i = 0; i < n; i++) {
    nxt[2 * i] = 2 * best[i] + (best[best[i]] == i);
    nxt[2 * i + 1] = 2 * best2[i] + (best[best2[i]] == i);
  }

  int nrciclu = 0;
  for(int i = 0; i < 2 * n; i++) {
    if(!viz[i]) {
      int j = i;
      while(!viz[j]) {
        viz[j] = 1;
        j = nxt[j];
      }
      if(ciclu[j] == 0) {
        int q = j, poz = 0;
        ciclu[j] = ++nrciclu;
        oncycle[j] = 1;
        cyclepoz[j] = ++poz;
        while(nxt[q] != j) {
          q = nxt[q];
          ciclu[q] = nrciclu;
          oncycle[q] = 1;
          cyclepoz[q] = ++poz;
        }
        cyclesz[nrciclu] = poz;
      }
      int q = i;
      while(q != j) {
        ciclu[q] = ciclu[j];
        q = nxt[q];
      }
    }
  }
  for(int i = 0; i < 2 * n; i++) {
    if(!oncycle[i]) {
      g[nxt[i]].push_back(i);
    }
  }
  for(int i = 0; i < 2 * n; i++) {
    if(oncycle[i]) {
      root[i] = i;
      dfs(i);
    }
  }

  for(int i = 0; i < n; i++) {
    solve(2 * i, 2 * p, 0);
    solve(2 * i, 2 * p + 1, 1);
  }

  sort(upd[0].begin(), upd[0].end());
  sort(upd[1].begin(), upd[1].end());
  for(int i = 0; i < q; i++) {
    ord[i] = i;
  }
  sort(ord, ord + q, [&](int a, int b) {
    return qval[a] < qval[b];
  });
  int ptr[2] = {0, 0}, sizes[2] = {cyclesz[ciclu[2 * p]], cyclesz[ciclu[2 * p + 1]]};
  for(int i = 0; i < q; i++) {
    while(ptr[0] < (int)upd[0].size() && upd[0][ptr[0]] <= qval[ord[i]]) {
      freq[0][upd[0][ptr[0]++] % sizes[0]]++;
    }
    while(ptr[1] < (int)upd[1].size() && upd[1][ptr[1]] <= qval[ord[i]]) {
      freq[1][upd[1][ptr[1]++] % sizes[1]]++;
    }
    answers[ord[i]] = freq[0][qval[ord[i]] % sizes[0]] + freq[1][qval[ord[i]] % sizes[1]];
    if(qval[ord[i]] <= 2 * n) {
      answers[ord[i]] += ans[qval[ord[i]]];
    }
  }

  for(int i = 0; i < q; i++) {
    answer(answers[i]);
  }
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…