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

#include <algorithm>
#include <cmath>
#include <functional>
#include <math.h>
#include <stdio.h>
#include <utility>
#include <vector>
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
void Input(std::vector<std::pair<int, int>> &vnnInput);
bool bCrossProduct(std::pair<int, int> &point,
                   std::vector<std::pair<int, int>> &StackPoints, int i);
int main(void) {
  int nInput;
  scanf("%d", &nInput);
  std::vector<std::pair<int, int>> vnnInput(nInput);
  Input(vnnInput);
  // vnniValuePoint((angle,lenght_2),n)
  std::vector<std::pair<std::pair<double, double>, size_t>> vnniValuePoint(
      nInput);
  vnniValuePoint[0] = std::pair<std::pair<double, double>, size_t>(
      std::pair<double, double>(0., 0.), 0);
  for (int i = 1; i < nInput; ++i) {
    int dX = vnnInput[i].first - vnnInput[0].first;
    int dY = vnnInput[i].second - vnnInput[0].second;
    int nLength_2 = dX * dX + dY * dY;
    vnniValuePoint[i].first.second = 1. * nLength_2;
    int GCD = gcd(std::abs(dX), std::abs(dY));
    dX /= GCD;
    nLength_2 /= (GCD * GCD);
    vnniValuePoint[i].first.first = std::acos(dX / std::sqrt(1. * nLength_2));
    vnniValuePoint[i].second = i;
  }
  std::stable_sort(vnniValuePoint.begin(), vnniValuePoint.end());
  int n = 0;
  for (int i = vnniValuePoint.size() - 2; i >= 0; --i) {
    if (std::abs(vnniValuePoint[vnniValuePoint.size() - 1].first.first -
                 vnniValuePoint[i].first.first) > 1.e-8) {
      break;
    }
    ++n;
  }

  std::vector<std::pair<int, int>> vnnSortedput(nInput);
  for (int i = 0; i < nInput; ++i) {
    vnnSortedput[i] = vnnInput[vnniValuePoint[i].second];
  }

  // std::sort(vnnSortedput.end()-n,vnnSortedput.end(),std::greater<
  // std::pair<int ,int> >());
  std::reverse(vnnSortedput.end() - n - 1, vnnSortedput.end());
  int iIndex = 0;
  for (int i = 1; i < nInput - 1; ++i) {
    vnnInput[++iIndex] = vnnSortedput[i];

    while (!bCrossProduct(vnnSortedput[i + 1], vnnInput, iIndex)) {
      --iIndex;
    }
  }
  vnnInput[++iIndex] = vnnSortedput[nInput - 1];

  printf("%d\\n", ++iIndex); //++??¢???????????????=????´???°

  for (int i = 0; i < iIndex; ++i) {
    printf("%d %d\\n", vnnInput[i].first, vnnInput[i].second);
  }
  // system("pause");
  return 0;
}

void Input(std::vector<std::pair<int, int>> &vnnInput) {
  for (int i = 0; i < vnnInput.size(); ++i) {
    scanf("%d%d", &vnnInput[i].second, &vnnInput[i].first);
  }
  std::sort(vnnInput.begin(), vnnInput.end());
  for (int i = 0; i < vnnInput.size(); ++i) {
    std::swap(vnnInput[i].first, vnnInput[i].second);
  }
}

bool bCrossProduct(std::pair<int, int> &point,
                   std::vector<std::pair<int, int>> &StackPoints, int i) {

  double dValueCrossPro;

  dValueCrossPro = (StackPoints[i].first - StackPoints[i - 1].first) *
                       (point.second - StackPoints[i].second) -
                   (StackPoints[i].second - StackPoints[i - 1].second) *
                       (point.first - StackPoints[i].first);
  return dValueCrossPro >= 0;
}

Error: TLE

Fixed submission:

#define _USE_MATH_DEFINES
#include <climits>
#include <cmath>

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <utility>
#include <vector>
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
class Points {
private:
  static std::pair<std::pair<int, int>, std::pair<int, int>> MinMaxArgWithGCD;
  std::pair<int, int> nGCDCood; //????????±????????¶?????????????¬??????§?¨?
  std::pair<int, int> nCood;    //??¶?????????????¬??????§?¨?
  double dArg;      //??¶?????????????§?????????¨??¶?????????????§?
  double dLength_2; //??¶?????????????§?????????¨??¶??????????????¢
public:
  Points() {
    nGCDCood.first = nGCDCood.second = 0;
    nCood.first = nCood.second = 0;
    dArg = dLength_2 = 0.;
  }
  void SetPoint(std::pair<int, int> &nInput) {
    nCood = nInput;
    return;
  }
  std::pair<int, int> nnGetCood() const { return nCood; }
  void SetArg(Points StartPoint) {
    nGCDCood.first = nCood.first - StartPoint.nnGetCood().first;
    nGCDCood.second = nCood.second - StartPoint.nnGetCood().second;
    int GCD = gcd(std::abs(nGCDCood.first), std::abs(nGCDCood.second));
    nGCDCood.first /= GCD;
    nGCDCood.second /= GCD;
    double dLengthVector = std::sqrt(1. * (nGCDCood.first * nGCDCood.first +
                                           nGCDCood.second * nGCDCood.second));
    double dCos = nGCDCood.first / dLengthVector;
    dArg = std::acos(dCos);
    return;
  }
  void SetLength(Points StartPoint) {
    dLength_2 = (nCood.first - StartPoint.nnGetCood().first) *
                    (nCood.first - StartPoint.nnGetCood().first) +
                (nCood.second - StartPoint.nnGetCood().second) *
                    (nCood.second - StartPoint.nnGetCood().second);
    return;
  }
  std::pair<int, int> nnGetBCDCood() const { return nGCDCood; }
  double dGetArg() const { return dArg; }
  double dGetLength_2() const { return dLength_2; }
  void SetMinMaxArg(std::pair<int, int> InputMin, std::pair<int, int> InputMax);
  std::pair<std::pair<int, int>, std::pair<int, int>> const GetMinMaxArg();
};
std::pair<std::pair<int, int>, std::pair<int, int>> Points::MinMaxArgWithGCD;
void Points::SetMinMaxArg(std::pair<int, int> InputMin,
                          std::pair<int, int> InputMax) {
  MinMaxArgWithGCD.first = InputMin;
  MinMaxArgWithGCD.second = InputMax;
  return;
}
std::pair<std::pair<int, int>, std::pair<int, int>> const
Points::GetMinMaxArg() {
  return MinMaxArgWithGCD;
}

/*
 *????????????????????? for dArg@points
 */
void quick_sort_part(std::vector<Points> &points, int left, int right);
int partition(std::vector<Points> &points, int left, int right);
bool bCheckIsometric(const std::vector<Points> &points, int left, int right);
/*
 *?????????????????????for dLength@points
 *nUpDown(1)??????
 *nUpDown(-1)??????
 **????????§????????????????¶?
 */
void quick_sort_part_2(std::vector<Points> &points, int nUpDown, int left,
                       int right);
int partition_2(std::vector<Points> &points, int nUpDown, int left, int right);

/*
?§????????°?????????§?????????????????????????????§??????????????????
????°??§????????????????
?????§?§????????????????
*/
/*
 *??????dArg??????????????????????????????????????????????????????
 *???????????¶?????????????§???????points[0]??????????????¢??§?±??????????
 *??¶??????points[0]->[1]??¨??????????????????
 *???????????????????????????????????????
 */
void judgeIsometric(std::vector<Points> &points);
bool bCrossProduct(Points &points,
                   std::vector<std::pair<int, int>> &StackPoints, int i);
/*
 *??????????¬?????????£(true)??????????????§???i???????????¶?????????????????????????????????
 *points[1]??¨[points.size()-1]???????????????
 *1<=i<=points.size()-2?????????????????????
 */

int main(void) {

  int nInput;
  scanf("%d", &nInput);

  std::vector<Points> aComp_nPoints(
      nInput); ///////??¶???????????????????????????????????£????????????
  std::pair<int, int> prnnInput;
  int nMinX = INT_MAX, nMinY = INT_MAX;
  int nIndexMin;

  for (int i = 0; i < nInput; ++i) {

    scanf("%d%d", &(prnnInput.first), &(prnnInput.second));
    aComp_nPoints[i].SetPoint(prnnInput);

    if (nMinY == prnnInput.second && nMinX > prnnInput.first) {
      nMinX = prnnInput.first;
      nIndexMin = i;
    } else if (nMinY > prnnInput.second) {
      nMinY = prnnInput.second;
      nMinX = prnnInput.first;
      nIndexMin = i;
    }
  }
  /*
   *??¶??????????????§y???????°??????§????????????????????§?????????x????°???????????????¢???
   */

  std::swap(aComp_nPoints[0], aComp_nPoints[nIndexMin]);

  double dMinArg = M_PI, dMaxArg = 0.;
  int nMin, nMax;
  for (int i = 1; i < nInput; ++i) {
    aComp_nPoints[i].SetArg(aComp_nPoints[0]);
    if (dMinArg > aComp_nPoints[i].dGetArg()) {
      dMinArg = aComp_nPoints[i].dGetArg();
      nMin = i;
    }
    if (dMaxArg < aComp_nPoints[i].dGetArg()) {
      dMaxArg = aComp_nPoints[i].dGetArg();
      nMax = i;
    }
  }
  //????°???¨?????§?§???????????????????
  aComp_nPoints[0].SetMinMaxArg(aComp_nPoints[nMin].nnGetBCDCood(),
                                aComp_nPoints[nMax].nnGetBCDCood());
  //????°??§???¨?????§?§???¨??????????????????????±?????????????
  for (int i = 1; i < nInput; ++i) {
    if (aComp_nPoints[i].nnGetBCDCood() ==
            aComp_nPoints[i].GetMinMaxArg().first ||
        aComp_nPoints[i].nnGetBCDCood() ==
            aComp_nPoints[i].GetMinMaxArg().second) {
      aComp_nPoints[i].SetLength(aComp_nPoints[0]);
    }
  }
  /*
   *aComp_nPoints[0]????????????????§?????±????????°?????????????aComp_nPoints[i>0]?????????????????????
   */
  quick_sort_part(aComp_nPoints, 0, aComp_nPoints.size() - 1);
  /*
   *????§??????????aComp_nPoints[0]??¨????????¢????±?????????????????????????
   */
  judgeIsometric(aComp_nPoints);
  /*
   *????????¨?????????????????????pnnPrintPoints?????\\?????????
   **?????????????????????????????¶????????¨??????????´?????¢?????????????????????§?????¢??????????§???£???
   */
  std::vector<std::pair<int, int>> pnnPrintPoints(aComp_nPoints.size());
  pnnPrintPoints[0] = aComp_nPoints[0].nnGetCood();
  int iIndex = 0;
  for (int i = 1; i < aComp_nPoints.size() - 1; ++i) {
    pnnPrintPoints[++iIndex] = aComp_nPoints[i].nnGetCood();

    while (!bCrossProduct(aComp_nPoints[i + 1], pnnPrintPoints, iIndex)) {
      --iIndex;
    }
  }
  pnnPrintPoints[++iIndex] =
      aComp_nPoints[aComp_nPoints.size() - 1].nnGetCood();

  printf("%d\\n", ++iIndex); //++??¢???????????????=????´???°

  for (int i = 0; i < iIndex; ++i) {
    printf("%d %d\\n", pnnPrintPoints[i].first, pnnPrintPoints[i].second);
  }
  // system ("pause");
  return 0;
}
int partition(std::vector<Points> &points, int left, int right) {

  double dValue = points[right].dGetArg();
  int iIndex = left - 1;  // dArg
  int iIndexL = left - 1; // dLength
  for (int j = left; j <= right - 1; ++j) {
    if (points[j].dGetArg() <= dValue) {
      ++iIndex;
      std::swap(points[iIndex], points[j]);
    }
  }
  std::swap(points[++iIndex], points[right]);
  // dValue = points[right].dGetLength_2();
  // if (iIndex == right
  //     && points[left].nnGetBCDCood() == points[left].GetMinMaxArg().first )
  //  {  for (int k = left;k <= right-1;++k){
  // if(points[k].dGetLength_2() <= dValue){
  //     ++iIndexL;
  //      std::swap(points[iIndexL],points[k]);
  //   }
  //}
  // std::swap(points[++iIndex],points[right]);
  //}else if (iIndex == right &&  points[left].nnGetBCDCood() ==
  //points[left].GetMinMaxArg().second  ) {  for (int k = left;k <=
  //right-1;++k){
  //  if(points[k].dGetLength_2() >= dValue){
  //     ++iIndexL;
  //       std::swap(points[iIndexL],points[k]);
  //    }
  // } std::swap(points[++iIndex],points[right]);
  // }
  // return iIndexL==left-1?iIndex:iIndexL;
  return iIndex;
}
void quick_sort_part(std::vector<Points> &points, int left, int right) {
  if (left < right) {
    int nMiddleIndex = partition(points, left, right);
    quick_sort_part(points, left, nMiddleIndex - 1);
    quick_sort_part(points, nMiddleIndex + 1, right);
  }

  return;
}
bool bCheckIsometric(const std::vector<Points> &points, int left, int right) {
  for (int i = left; i < right; ++i) {
    if (points[i].nnGetBCDCood() != points[i + 1].nnGetBCDCood()) {
      return false;
    }
  }
  return true;
}
int partition_2(std::vector<Points> &points, int nUpDown, int left, int right) {

  double dValue = points[right].dGetLength_2();
  int iIndex = left - 1;
  for (int j = left; j <= right - 1; ++j) {
    if (nUpDown == 1 && points[j].dGetLength_2() <= dValue) {
      ++iIndex;
      std::swap(points[iIndex], points[j]);
    } else if (nUpDown == -1 && points[j].dGetLength_2() >= dValue) {
      ++iIndex;
      std::swap(points[iIndex], points[j]);
    }
  }
  std::swap(points[iIndex + 1], points[right]);
  return iIndex + 1;
}
void quick_sort_part_2(std::vector<Points> &points, int nUpDown, int left,
                       int right) {
  if (left < right) {
    int nMiddleIndex = partition_2(points, nUpDown, left, right);
    quick_sort_part_2(points, nUpDown, left, nMiddleIndex - 1);
    quick_sort_part_2(points, nUpDown, nMiddleIndex + 1, right);
  }

  return;
}
void judgeIsometric(std::vector<Points> &points) {
  points[points.size() - 1].SetLength(points[0]);
  int iLeft = 1, iRight = 1;
  for (int i = 1; i < points.size() - 1; ++i) {
    if (bCheckIsometric(points, i, i + 1)) {
      iRight = i + 1;
      if (!points[i].dGetLength_2()) {
        points[i].SetLength(points[0]);
      }
      points[i + 1].SetLength(points[0]);
      if (iRight == points.size() - 1) {
        quick_sort_part_2(points, -1, iLeft, iRight);
      }
    } else {
      if (iLeft != iRight) {
        if (iLeft == 1) {
          quick_sort_part_2(points, 1, iLeft, iRight);
        }

        else {
          quick_sort_part_2(points, -1, iLeft, iRight);
          points.erase(points.begin() + iLeft + 1, points.begin() + iRight);
        }
      }
      iLeft = iRight = i + 1;
    }
  }
  return;
}
bool bCrossProduct(Points &points,
                   std::vector<std::pair<int, int>> &StackPoints, int i) {

  double dValueCrossPro;

  dValueCrossPro = (StackPoints[i].first - StackPoints[i - 1].first) *
                       (points.nnGetCood().second - StackPoints[i].second) -
                   (StackPoints[i].second - StackPoints[i - 1].second) *
                       (points.nnGetCood().first - StackPoints[i].first);
  return dValueCrossPro >= 0;
}