Cod sursă (job #786245)

Utilizator avatar grecu_tudor Grecu Tudor grecu_tudor IP ascuns
Problemă Burlane Compilator cpp-32 | 1,48 kb
Rundă Arhiva de probleme Status evaluat
Dată 15 sept. 2024 08:26:22 Scor 100
#include <bits/stdc++.h>

using namespace std;

const int DIM = 1e5;

ifstream fin( "burlane.in" );
ofstream fout( "burlane.out" );

int nxt[1 + DIM], bucket[1 + DIM];
int nxt_out[1 + DIM]; // next out of bucket
int dist_out[1 + DIM]; // distance out of bucket

void read( int &n, int &q ) {
  fin >> n >> q;
  for ( int i = 1; i <= n; ++i ) {
    fin >> nxt[i];
  }
}

void init( int n ) { 
  int bsize = sqrt(n);
  for ( int i = 1; i <= n; ++i ) {
    bucket[i] = (i - 1) / bsize + 1;
    int j = i;
    while ( bucket[i] == bucket[j] ) {
      ++dist_out[i];
      j = nxt[j];
    }
    nxt_out[i] = j;
  }
}

void repair_bucket( int n, int x, int bk ) {
  while ( x <= n && bucket[x] == bk ) {
    if ( bucket[nxt[x]] == bk ) {
      dist_out[x] = dist_out[nxt[x]] + 1;
      nxt_out[x] = nxt_out[nxt[x]];
    }
    ++x; 
  }
}

void update( int n, int x, int y ) {
  if ( bucket[y] != bucket[x] ) {
    nxt_out[x] = y;
    dist_out[x] = 1;
  }
  nxt[x] = y;
  repair_bucket(n, x, bucket[x]);  
}

int query( int x ) {
  int dist = 0;
  while ( x ) {
    dist += dist_out[x];
    x = nxt_out[x];
  }
  return dist;
}

int main() {
  ios_base::sync_with_stdio(0);
  fin.tie(0);
  int n, q, x, y, type;
  
  read(n, q);
  init(n);
  while ( q-- ) {
    fin >> type >> x;
    if ( type == 2 ) {
      fin >> y;
      update(n, x, y);
    } else {
      fout << query(x) << "\n";
    }
  }
  fin.close();
  fout.close();
  return 0;
}