Submission #5745

#TimeUsernameProblemLanguageResultExecution timeMemory
5745model_code사회적 불평등 (TOKI14_social)C++98
100 / 100
96 ms4408 KiB
/* * Official Solution * * Social Inequality * Derianto Kusuma */ #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <math.h> #define MAX_N 100001 int n; long long x[MAX_N]; long long y[MAX_N]; // Merge sort temp buffer long long xTemp[MAX_N]; long long yTemp[MAX_N]; bool isLeftDivision[MAX_N]; bool isLeftDivisionTemp[MAX_N]; void sortByX(int left, int right) { if (left >= right) return; int p1 = left, p2 = right; long long pivotX = x[(left + right) / 2]; long long temp; while (p1 < p2) { while (x[p1] < pivotX) p1++; while (x[p2] > pivotX) p2--; if (p1 < p2) { // Swap temp = x[p1]; x[p1] = x[p2]; x[p2] = temp; temp = y[p1]; y[p1] = y[p2]; y[p2] = temp; } if (p1 <= p2) { p1++; p2--; } } sortByX(left, p2); sortByX(p1, right); } long long longAbs(long long a) { if (a >= 0) return a; else return -a; } void readInput() { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%lld %lld", &x[i], &y[i]); } // Sort by x sortByX(0, n - 1); } void mergeSortByY(int left1, int right1, int left2, int right2) { int posResult = left1; int pos1 = left1; int pos2 = left2; while (true) { if (pos1 <= right1 && pos2 <= right2) { if (y[pos1] <= y[pos2]) { xTemp[posResult] = x[pos1]; yTemp[posResult] = y[pos1]; isLeftDivisionTemp[posResult] = isLeftDivision[pos1]; posResult++; pos1++; } else { xTemp[posResult] = x[pos2]; yTemp[posResult] = y[pos2]; isLeftDivisionTemp[posResult] = isLeftDivision[pos2]; posResult++; pos2++; } } else if (pos1 <= right1) { xTemp[posResult] = x[pos1]; yTemp[posResult] = y[pos1]; isLeftDivisionTemp[posResult] = isLeftDivision[pos1]; posResult++; pos1++; } else if (pos2 <= right2) { xTemp[posResult] = x[pos2]; yTemp[posResult] = y[pos2]; isLeftDivisionTemp[posResult] = isLeftDivision[pos2]; posResult++; pos2++; } else { break; } } assert(pos1 == right1 + 1); assert(pos2 == right2 + 1); assert(posResult == right2 + 1); // Copy from temp buffer to real buffer for (int i = left1; i <= right2; i++) { x[i] = xTemp[i]; y[i] = yTemp[i]; isLeftDivision[i] = isLeftDivisionTemp[i]; } } long long getSumDxFromRightX(int minIndex, int maxIndex, int rightX) { long long result = 0; for (int i = minIndex; i <= maxIndex; i++) { if (isLeftDivision[i]) { result += rightX - x[i]; } } return result; } long long getSumDyFromBottomY(int minIndex, int maxIndex, int bottomY) { long long result = 0; for (int i = minIndex; i <= maxIndex; i++) { if (isLeftDivision[i]) { result += y[i] - bottomY; } } return result; } long long getSumAreaToRightBottom(int minIndex, int maxIndex, int rightX, int bottomY) { long long result = 0; for (int i = minIndex; i <= maxIndex; i++) { if (isLeftDivision[i]) { result += (rightX - x[i]) * (y[i] - bottomY); } } return result; } long long rec(int minIndex, int maxIndex) { if (minIndex >= maxIndex) return 0; int middle = (minIndex + maxIndex) / 2; long long middleX = x[middle]; // Divide long long leftAnswer = rec(minIndex, middle); long long rightAnswer = rec(middle + 1, maxIndex); long long answer = leftAnswer + rightAnswer; // Data for merging operation long long nLeftBottomOfSweepLine; long long nLeftTopOfSweepLine; long long sumLeftDxBottomOfSweepLine; long long sumLeftDxTopOfSweepLine; long long sumLeftDyBottomOfSweepLine; long long sumLeftDyTopOfSweepLine; long long sumLeftAreaBottomOfSweepLine; long long sumLeftAreaTopOfSweepLine; int sweepLineIndex; long long sweepLineY; long long sweepLineDy; long long pointSpecificAnswer; // Set up point divisions before merging for (int i = minIndex; i <= maxIndex; i++) isLeftDivision[i] = (i <= middle); // Merge - sort by y - retaining isLeftDivision value so we can still distinguish which // points were originally from the left / right divisions mergeSortByY(minIndex, middle, middle + 1, maxIndex); // Initialize merging operation data at sweepLineY = bottom Y sweepLineY = y[minIndex]; nLeftBottomOfSweepLine = 0; nLeftTopOfSweepLine = middle - minIndex + 1; sumLeftDxBottomOfSweepLine = 0; sumLeftDxTopOfSweepLine = getSumDxFromRightX(minIndex, maxIndex, middleX); sumLeftDyBottomOfSweepLine = 0; sumLeftDyTopOfSweepLine = getSumDyFromBottomY(minIndex, maxIndex, sweepLineY); sumLeftAreaBottomOfSweepLine = 0; sumLeftAreaTopOfSweepLine = getSumAreaToRightBottom(minIndex, maxIndex, middleX, sweepLineY); // Sweep from bottom to top for (sweepLineIndex = minIndex; sweepLineIndex <= maxIndex; sweepLineIndex++) { sweepLineY = y[sweepLineIndex]; sweepLineDy = (sweepLineIndex == minIndex) ? 0 : sweepLineY - y[sweepLineIndex - 1]; // Update operational data sumLeftDyBottomOfSweepLine += nLeftBottomOfSweepLine * sweepLineDy; sumLeftDyTopOfSweepLine -= nLeftTopOfSweepLine * sweepLineDy; sumLeftAreaBottomOfSweepLine += sumLeftDxBottomOfSweepLine * sweepLineDy; sumLeftAreaTopOfSweepLine -= sumLeftDxTopOfSweepLine * sweepLineDy; if (isLeftDivision[sweepLineIndex]) { // Point is in the left division - add a point under sweep line sumLeftDxBottomOfSweepLine += (middleX - x[sweepLineIndex]); sumLeftDxTopOfSweepLine -= (middleX - x[sweepLineIndex]); nLeftBottomOfSweepLine++; nLeftTopOfSweepLine--; } else { // Point is in the right division - update answer pointSpecificAnswer = sumLeftAreaBottomOfSweepLine + sumLeftAreaTopOfSweepLine + sumLeftDyBottomOfSweepLine * (x[sweepLineIndex] - middleX) + sumLeftDyTopOfSweepLine * (x[sweepLineIndex] - middleX); answer += pointSpecificAnswer; } } return answer; } void writeOutput() { long long result = rec(0, n - 1); printf("%lld\n", result); } int main() { readInput(); writeOutput(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...