Problem p00459 (C++) — buggy submission, verdict: Time Limit Exceeded


#include <iostream>
using namespace std;
int cards, n, i, p, q, r, x[5002], y[5002], counter;
int numberStart[20001];
int numberFast[20001];
int numberEnd[20001];
int searchB[20001];
int numberLong(int value) { return numberEnd[value] - numberStart[value] + 1; }

int searchD(int seed) {
  int l = 0;
  for (int a = 1; a <= counter + 1; a++) {
    if (seed > l + numberLong(searchB[a])) {
      l += numberLong(searchB[a]);
    } else {
      return numberFast[searchB[a]];
    }
  }
  return -100;
}
int searchNumber(int value) {
  int l = 0;
  for (int a = 1; a <= counter + 1; a++) {
    if (value > l + numberLong(searchB[a])) {
      l += numberLong(searchB[a]);
    } else {
      return numberStart[searchB[a]] + value - l - 1;
    }
  }
  return -100;
}

void cut(int g) {
  if (searchD(g) == searchD(g + 1)) {
    // カットする場所が入ってる数列を求める
    int searchNumberG = searchNumber(g);
    int seachX = searchB[searchD(g)];
    int seachXX = searchNumberG;
    // 数列ができる範囲の後ろの番号FASTを変える
    for (int j = 1; j <= counter; j++) {
      if (numberFast[j] >= numberFast[seachX] + 1) {
        numberFast[j]++;
      }
    }

    // の数列の後ろに新しい数列を作る
    counter++;
    numberFast[counter] = numberFast[seachX] + 1;
    numberStart[counter] = searchNumberG + 1;
    numberEnd[counter] = numberEnd[seachX];
    // できた数列の前の数列の最後を調整する
    numberEnd[seachX] = searchNumberG;

    for (int a = 1; a <= counter + 1; a++) {
      searchB[numberFast[a]] = a;
    }
  }
}
void shuffle(int x, int y) {

  int StartHead[10001];
  int numberFastNew[10001];

  int longs = 1;
  for (int i = 1; i <= counter; i++) {
    StartHead[searchB[i]] = longs;
    longs += numberLong(searchB[i]);
  }
  int newCounter[3];
  for (int i = 0; i < 3; i++) {
    newCounter[i] = 0;
  }
  for (int j = 1; j <= counter; j++) {
    if (StartHead[j] > y) {
      newCounter[0]++;
      numberFastNew[j] = 0;
    }
    if (StartHead[j] > x && StartHead[j] + numberLong(j) - 1 <= y) {
      newCounter[1]++;
      numberFastNew[j] = 1;
    }
    if (StartHead[j] + numberLong(j) - 1 <= x) {
      newCounter[2]++;
      numberFastNew[j] = 2;
    }
  }

  for (int j = 1; j <= counter; j++) {
    switch (numberFastNew[j]) {
    case 0:
      numberFast[j] += -newCounter[1] - newCounter[2];
      break;
    case 1:
      numberFast[j] += newCounter[0] - newCounter[2];
      break;
    case 2:
      numberFast[j] += newCounter[1] + newCounter[0];
      break;
    }
  }
  for (int a = 1; a <= counter + 1; a++) {
    searchB[numberFast[a]] = a;
  }
}

int main(void) {
  while (true) {
    cards = 0;
    n = 0;
    counter = 0;
    for (int i = 0; i < 20000; i++) {
      numberStart[i] = 0;
      numberFast[i] = 0;
      numberEnd[i] = 0;
      searchB[i] = 0;
    }
    int points = 0;
    counter = 1;
    cin >> cards;
    if (cards == 0) {
      break;
    }
    numberStart[1] = 1;
    numberEnd[1] = cards;
    numberFast[1] = 1;
    searchB[1] = 1;
    cin >> n;
    cin >> p >> q >> r;
    for (i = 1; i <= n; i++) {
      cin >> x[i] >> y[i];
    }
    for (i = 1; i <= n; i++) {
      cut(x[i]);

      cut(y[i]);

      shuffle(x[i], y[i]);
    }
    cut(p - 1);
    cut(q);
    /*

     for(int j=1;j<=counter;j++){

       cout << numberStart[j] << " "  <<  numberEnd[j] << " " << numberFast[j]
     <<  endl;

     }
     cout << searchD(p) << searchD(q) <<endl;
     */
    for (int j = 1; j <= counter; j++) {
      if (searchD(p) <= numberFast[j] && numberFast[j] <= searchD(q)) {
        if (numberEnd[j] <= r) {
          points += numberLong(j);
        } else if (numberStart[j] <= r) {
          points += numberLong(j) - (numberEnd[j] - r);
        }
      }
    }
    cout << points << endl;
  }
}

Error: TLE

Fixed submission:


#include <iostream>
using namespace std;
int cards, n, i, p, q, r, x[5000], y[5000], counter;
int numberStart[10001];
int numberFast[10001];
int numberEnd[10001];
int searchB[10001];
int numberLong(int value) { return numberEnd[value] - numberStart[value] + 1; }

int searchD(int seed) {
  int l = 0;
  for (int a = 1; a <= counter + 1; a++) {
    if (seed > l + numberLong(searchB[a])) {
      l += numberLong(searchB[a]);
    } else {
      return numberFast[searchB[a]];
    }
  }
  return -100;
}
int searchNumber(int value) {
  int l = 0;
  for (int a = 1; a <= counter + 1; a++) {
    if (value > l + numberLong(searchB[a])) {
      l += numberLong(searchB[a]);
    } else {
      return numberStart[searchB[a]] + value - l - 1;
    }
  }
  return -100;
}

void cut(int g) {
  if (searchD(g) == searchD(g + 1)) {
    // カットする場所が入ってる数列を求める
    int searchNumberG = searchNumber(g);
    int seachX = searchB[searchD(g)];
    int seachXX = searchNumberG;
    // 数列ができる範囲の後ろの番号FASTを変える
    for (int j = 1; j <= counter; j++) {
      if (numberFast[j] >= numberFast[seachX] + 1) {
        numberFast[j]++;
      }
    }

    // の数列の後ろに新しい数列を作る
    counter++;
    numberFast[counter] = numberFast[seachX] + 1;
    numberStart[counter] = searchNumberG + 1;
    numberEnd[counter] = numberEnd[seachX];
    // できた数列の前の数列の最後を調整する
    numberEnd[seachX] = searchNumberG;

    for (int a = 1; a <= counter + 1; a++) {
      searchB[numberFast[a]] = a;
    }
  }
}
void shuffle(int x, int y) {

  int StartHead[10001];
  int numberFastNew[10001];

  int longs = 1;
  for (int i = 1; i <= counter; i++) {
    StartHead[searchB[i]] = longs;
    longs += numberLong(searchB[i]);
  }
  int newCounter[3];
  for (int i = 0; i < 3; i++) {
    newCounter[i] = 0;
  }
  for (int j = 1; j <= counter; j++) {
    if (StartHead[j] > y) {
      newCounter[0]++;
      numberFastNew[j] = 0;
    }
    if (StartHead[j] > x && StartHead[j] + numberLong(j) - 1 <= y) {
      newCounter[1]++;
      numberFastNew[j] = 1;
    }
    if (StartHead[j] + numberLong(j) - 1 <= x) {
      newCounter[2]++;
      numberFastNew[j] = 2;
    }
  }

  for (int j = 1; j <= counter; j++) {
    switch (numberFastNew[j]) {
    case 0:
      numberFast[j] += -newCounter[1] - newCounter[2];
      break;
    case 1:
      numberFast[j] += newCounter[0] - newCounter[2];
      break;
    case 2:
      numberFast[j] += newCounter[1] + newCounter[0];
      break;
    }
  }
  for (int a = 1; a <= counter + 1; a++) {
    searchB[numberFast[a]] = a;
  }
}

int main(void) {
  while (true) {
    cards = 0;
    n = 0;
    counter = 0;
    for (int i = 0; i < 10001; i++) {
      numberStart[i] = 0;
      numberFast[i] = 0;
      numberEnd[i] = 0;
      searchB[i] = 0;
    }
    int points = 0;
    counter = 1;
    cin >> cards;
    if (cards == 0) {
      break;
    }
    numberStart[1] = 1;
    numberEnd[1] = cards;
    numberFast[1] = 1;
    searchB[1] = 1;
    cin >> n;
    cin >> p >> q >> r;
    for (i = 1; i <= n; i++) {
      cin >> x[i] >> y[i];
    }
    for (i = 1; i <= n; i++) {
      cut(x[i]);

      cut(y[i]);

      shuffle(x[i], y[i]);
    }

    for (int j = p; j <= q; j++) {
      if (searchNumber(j) <= r) {
        points++;
      }
    }
    cout << points << endl;
  }
}