欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ3170: [Tjoi2013]松鼠聚会 - 暴力

发布时间:2023/12/18 编程问答 47 豆豆
生活随笔 收集整理的这篇文章主要介绍了 BZOJ3170: [Tjoi2013]松鼠聚会 - 暴力 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

描述

有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

题解

简直就是个高中数学题啊。。。蒟蒻数学不好,学不来呜

松鼠$i $ 和 $j$ 的距离为$ \max{\left\vert X_i - X_j \right\vert, \left\vert Y_i - Y_j\right\vert } $

但是我们不能在很短的时间内求出对于所有$i$和$j$ 的$\max$, 所以只能通过加绝对值让$\max$去掉。

首先1.  $\max{a, b} = (\left\vert a + b\right\vert + \left\vert a - b\right\vert) \div 2$

并且 2.$ \left\vert \left\vert a\right\vert - \left\vert b\right\vert \right\vert + \left\vert \left\vert a\right\vert  + \left\vert b\right\vert \right\vert  = \left\vert a - b\right\vert + \left\vert a + b\right\vert$

我们通过式子1算出$ \max{\left\vert X_i - X_j \right\vert, \left\vert Y_i - Y_j\right\vert }  = ( \left\vert \left\vert  X_i - X_j \right\vert - \left\vert Y_i - Y_j\right\vert \right\vert + \left\vert \left\vert X_i - X_j \right\vert  + \left\vert Y_i - Y_j \right\vert \right\vert ) \div 2$

然后再通过2式就变成了 $( \left\vert ( X_i-Y_i ) - (X_j - Y_j) \right\vert + \left\vert (X_i - Y_i)  + (X_j - Y_j) \right\vert) \div 2$

令$a_i = X_i - Y_i $ $b_i = X_i + Y_i$

算出所有的$\left\vert a_i  - a_j \right\vert $ 和$\left\vert b_i - b_j\right\vert$ 再除 2, 取答案最小的$i$

算$\left\vert a_i  - a_j \right\vert $ 时需要排序求前缀和计算。

 

打绝对值累死我了。。、

代码

 

1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #define rd read() 5 #define ll long long 6 using namespace std; 7 8 const int N = 2e5; 9 10 ll sumx[N], sumy[N], n, ans = 1e18; 11 12 struct node { 13 ll x, y; 14 ll xx, yy; 15 ll disx, disy; 16 }a[N]; 17 18 ll read() { 19 ll X = 0, p = 1; char c = getchar(); 20 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 21 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 22 return X * p; 23 } 24 25 int cmpx(const node &A, const node &B ) { 26 return A.xx < B.xx; 27 } 28 29 int cmpy(const node &A, const node &B) { 30 return A.yy < B.yy; 31 } 32 33 int main() 34 { 35 n = rd; 36 for(int i = 1; i <= n; ++i) { 37 a[i].x = rd * 2; 38 a[i].y = rd * 2; 39 a[i].xx = (a[i].x + a[i].y) >> 1; 40 a[i].yy = (a[i].x - a[i].y) >> 1; 41 } 42 sort(a+1, a+1+n, cmpx); 43 for(int i = 1; i <= n; ++i) sumx[i] = sumx[i - 1] + a[i].xx; 44 for(int i = 1; i <= n; ++i) { 45 a[i].disx = a[i].xx * i - sumx[i]; 46 a[i].disx += sumx[n] - sumx[i] - (n - i) * a[i].xx; 47 } 48 sort(a+1, a+1+n, cmpy); 49 for(int i = 1; i <= n; ++i) sumy[i] = sumy[i - 1] + a[i].yy; 50 for(int i = 1; i <= n; ++i) { 51 a[i].disy = a[i].yy * i - sumy[i]; 52 a[i].disy += sumy[n] - sumy[i] - (n - i) * a[i].yy; 53 if(a[i].disy + a[i].disx < ans) ans = a[i].disx + a[i].disy; 54 } 55 printf("%lld\n", ans >> 1); 56 } View Code

 

转载于:https://www.cnblogs.com/cychester/p/9522469.html

总结

以上是生活随笔为你收集整理的BZOJ3170: [Tjoi2013]松鼠聚会 - 暴力的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。