離散化_二分_字首和_POJ3179_Corral the Cows
阿新 • • 發佈:2018-12-18
題目概述: 計算包含C個點的正方形的最小邊長
思路分析:
由於每個點的橫縱座標最大可能為10000, 題目記憶體限制為65536K, 如果申請一個int[10000][10000]那麼顯然直接記憶體超出限制, 考慮到至多給定500個點, 因此橫縱座標的各自最多有500個不同取值, 因此對橫縱座標分別離散化, 然後二分答案, 具體如下AC程式碼所示.
//POJ3179_Corral the Cows #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAX = 5e2 + 5, NIL = 0x3f3f3f3f; pair<int, int> p[MAX];//儲存輸入座標,first:x, second:y int disx[MAX], disy[MAX], xlen, ylen, g[MAX][MAX], C, N; //返回g[][]右上角頂點為(xmax, ymax), 左下角頂點為(xmin, ymin)的矩形區域的草數 int getSum(int xmax, int ymax, int xmin, int ymin){ return g[xmax][ymax] - g[xmin - 1][ymax] - g[xmax][ymin - 1] + g[xmin - 1][ymin - 1]; } //如果存在邊長為len的正方形包含的草數不少於C則返回true, 否則返回false bool judge(int len){ //列舉正方形右上角頂點 for(int xmax = xlen, xmin, ymin; xmax >= 1; --xmax) for(int ymax = ylen; ymax >= 1; --ymax){ xmin = lower_bound(disx + 1, disx + xmax + 1, disx[xmax] - len + 1) - disx; ymin = lower_bound(disy + 1, disy + ymax + 1, disy[ymax] - len + 1) - disy; if(getSum(xmax, ymax, xmin, ymin) >= C) return true; if(ymin == 1) break; } return false; } int main(){ scanf("%d %d", &C, &N); for(int i = 1; i <= N; ++i) scanf("%d %d", &p[i].first, &p[i].second), disx[i] = p[i].first, disy[i] = p[i].second; sort(disx + 1, disx + N + 1), xlen = unique(disx + 1, disx + N + 1) - (disx + 1); sort(disy + 1, disy + N + 1), ylen = unique(disy + 1, disy + N + 1) - (disy + 1); //下面初始化g[][] for(int i = 1, x, y; i <= N; ++i) x = lower_bound(disx + 1, disx + xlen + 1, p[i].first) - disx , y = lower_bound(disy + 1, disy + ylen + 1, p[i].second) - disy, ++g[x][y]; //下面初始化g為其字首和 for(int i = 1; i <= xlen; ++i) for(int j = 1; j <= ylen; ++j) g[i][j] = g[i][j] + g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1]; int l = 1, r = max(disx[xlen], disy[ylen]), mid; while(mid = l + r >> 1, l < r) if(judge(mid)) r = mid; else l = mid + 1; cout << l << endl; }