5775. 【NOIP2008模拟】农夫约的假期
(File IO): input:shuru.in output:shuru.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSetHint
题目保证z=1
做法:可以发现横纵是互不影响的,且q实际上不会对点的选取造成影响。可以考虑分别求出横纵坐标。1.利用中位数思想,在某个坐标左边(上边)的点数恰好大于等于右边(下边)的点数,此时该坐标最优。
2.一种浅显的做法是,横纵分别跑前缀和,这个算出每个点到第一个点的距离(横或纵)后,可以O(1)更新答案,取最小值。
代码如下:
第二种做法:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 2000007 5 #define LL long long 6 using namespace std; 7 LL n, m, z; 8 LL x[N], y[N], q[N], t_x[N], t_y[N], q_x[N], q_y[N]; 9 LL f[N], g[N], site_x, ans, site_y; 10 11 void work_x() 12 { 13 LL sum = 10000000000000; 14 for (int i = 1; i <= m; i++) 15 f[0] += x[i]; 16 for (int i = 1; i <= n; i++) 17 q_x[i] += t_x[i] + q_x[i - 1]; 18 for (int i = 1; i <= n; i++) 19 { 20 f[i] = f[i - 1] - (q_x[n] - q_x[i - 1]) + q_x[i - 1]; 21 if (f[i] < sum) 22 { 23 sum = f[i]; 24 site_x = i; 25 } 26 } 27 } 28 29 void work_y() 30 { 31 LL sum = 10000000000000; 32 for (int i = 1; i <= m; i++) 33 g[0] += y[i]; 34 for (int i = 1; i <= n; i++) 35 q_y[i] += t_y[i] + q_y[i - 1]; 36 for (int i = 1; i <= n; i++) 37 { 38 g[i] = g[i - 1] - (q_y[n] - q_y[i - 1]) + q_y[i - 1]; 39 if (g[i] < sum) 40 { 41 sum = g[i]; 42 site_y = i; 43 } 44 } 45 } 46 47 LL abs(LL x) 48 { 49 return x > 0 ? x : -x; 50 } 51 52 53 int main() 54 { 55 freopen("shuru.in", "r", stdin); 56 freopen("shuru.out", "w", stdout); 57 scanf("%lld%lld%lld", &n, &m, &z); 58 ans = 0; 59 for (int i = 1; i <= m; i++) 60 { 61 scanf("%lld%lld%lld", &x[i], &y[i], &q[i]); 62 t_x[x[i]]++; 63 t_y[y[i]]++; 64 ans += q[i]; 65 } 66 work_x(); 67 work_y(); 68 for (int i = 1; i <= n; i++) 69 { 70 ans += abs(site_x - (LL)i) * t_x[i]; 71 ans += abs(site_y - (LL)i) * t_y[i]; 72 } 73 printf("%lld\n", ans); 74 printf("%lld %lld", site_x, site_y); 75 }