poj1723 SOLDIERS
soldiers真乃神题也!
行列显然可以分开处理。
行好办,显然就是一个货仓选址问题,取中位数即可。
列呢??
??????
因为懒得推式子,用不了二分,我决定使用枚举大法!一算复杂度O(n^2),勉强可以卡过。
于是我做好了卡常数的准备,正在实现枚举及求值时,得到了援助:
你把士兵按照x排序,然后把x[i] - i即可转化为行上面的。
我略加思索:排好后是x[1], x[1] + 1, x[i] + 2, ..., x[i] + (i - 1)
那么我事先减去,便是x[1], x[1], x[1], ..., x[1]
妙啊,妙啊!
关于为何排序:使用了一点贪心的思想:如果一个A在B左边,那么排好队之后A也一定在B左边。
然后我抱着试一试的心态,过了样例,一口气AC了!!!
我们学到了什么?
转换:减去i
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using std::sort; 5 inline void read(int &x) { 6 x = 0; 7 bool f = 0; 8 char c = getchar(); 9 while(c < '0' || c > '9') { 10 if(c == '-') { 11 f = 1; 12 } 13 c = getchar(); 14 } 15 while(c <= '9' && c >= '0') { 16 x = (x << 3) + (x << 1) + c - '0'; 17 c = getchar(); 18 } 19 if(f) x = -x; 20 return; 21 } 22 inline void max(int &a, int b) { 23 if(a < b) a = b; 24 return; 25 } 26 inline void min(int &a, int b) { 27 if(a > b) a = b; 28 return; 29 } 30 inline int ab(int x) { 31 return (x < 0) ? ((~x) + 1) : x; 32 } 33 const int N = 10005, INF = 0x7f7f7f7f; 34 35 int x[N], y[N], n; 36 37 int main() { 38 int lx = -INF, sx = INF; 39 int xx, yy; 40 read(n); 41 for(int i = 1; i <= n; i++) { 42 read(x[i]); 43 read(y[i]); 44 } 45 46 long long ans = 0; 47 48 ///solve y -> 1 49 sort(y + 1, y + n + 1); 50 int k = y[(n + 1) >> 1]; 51 for(int i = 1; i <= n; i++) { 52 ans += ab(y[i] - k); 53 } 54 55 /// solve x -> [] 56 sort(x + 1, x + n + 1); 57 for(int i = 1; i <= n; i++) { 58 x[i] -= (i - 1); 59 } 60 sort(x + 1, x + n + 1); 61 k = x[(n + 1) >> 1]; 62 for(int i = 1; i <= n; i++) { 63 ans += ab(x[i] - k); 64 } 65 66 printf("%lld", ans); 67 return 0; 68 }