文章目录
P3964 [TJOI2013]松鼠聚会
思路:
坐标由 Q Q Q 转化为 M M M 后,问题可转化为,找到一个 k ∈ [ 1 , n ] k∈[1,n] k∈[1,n] 使得 s u m k = ∑ i = 1 n ∣ x i − x k ∣ + ∑ i = 1 n ∣ y i − y k ∣ sum_k=\sum_{i=1}^n{|x_i-x_k|}+\sum_{i=1}^n{|y_i-y_k|} sumk=∑i=1n∣xi−xk∣+∑i=1n∣yi−yk∣ 最小。
然后可以排序+前缀和+二分。
tips: P Q P_Q PQ 转化为 P M P_M PM 时,要除以2,会出现分数。因此我们最后对答案除以2即可,因为根据距离 Q Q Q 的距离公式发现,距离与坐标的关系是线性的。 M M M 距离同理。
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define abs(x) (((x)<0)?-(x):(x))
const int N=1e5+10;
typedef long long LL;
int x[N],y[N];
int bx[N],by[N];
LL sumx[N],sumy[N];
int main()
{
int n, xx, yy; scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d %d",&xx, &yy);
x[i] = bx[i] = xx + yy; y[i] = by[i] = xx - yy;
}
sort(bx + 1, bx + n + 1);
sort(by + 1, by + n + 1);
for(int i=1; i<=n; i++) sumx[i] = sumx[i - 1] + bx[i], sumy[i] = sumy[i - 1] + by[i];
LL ans = 1e18;
for(int i=1; i<=n; i++)
{
LL idx = lower_bound(bx + 1, bx + 1 + n, x[i]) - bx;
LL sum = (idx - 1) * x[i] - sumx[idx - 1] + sumx[n] - sumx[idx] - (n - idx) * x[i];
idx = lower_bound(by + 1, by + 1 + n, y[i]) - by;
sum += (idx - 1) * y[i] - sumy[idx - 1] + sumy[n] - sumy[idx] - (n - idx) * y[i];
ans = min(ans, sum);
}
printf("%lld",ans/2);
system("pause");
return 0;
}
AT3557 Four Coloring
思路:见洛谷题解,写的很好
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e7+10;
typedef long long LL;
char col[2][2] = {'R','Y','G','B'};
int main()
{
int h, w, d; cin>>h>>w>>d;
for(int i=1; i<=h; i++)
for(int j=1; j<=w; j++)
{
int x = i + j, y = i - j + max(h, w);
printf("%c",col[(x / d) & 1][(y / d) & 1]);
if(j == w) printf("\n");
}
system("pause");
return 0;
}
【多维曼哈顿最远点对】poj 2926 Requirements
题意:求五维曼哈顿距离最远点对。
题解:POJ 2926 题解
思路:
- 对于二维
a n s = m a x ( m a x { ( x + y ) − ( x j + y j ) ( x − y ) − ( x j − y j ) ( − x + y ) − ( − x j + y j ) ( − x − y ) − ( − x j − y j ) } , m a x ( . . . . . . ) , . . . . . . ) (2) ans=max(max\left\{\begin{matrix}(x+y)-(x_j+y_j)\\(x-y)-(x_j-y_j)\\(-x+y)-(-x_j+y_j)\\(-x-y)-(-x_j-y_j)\end{matrix}\right\} \tag{2},max(......),......) ans=max(max⎩⎪⎪⎨⎪⎪⎧(x+y)−(xj+yj)(x−y)−(xj−yj)(−x+y)−(−xj+yj)(−x−y)−(−xj−yj)⎭⎪⎪⎬⎪⎪⎫,max(......),......)(2)
-
也就是在四个状态下维护最大最小值,最后从四个状态中更新即可。
-
五维也同理。
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e5+10;
typedef long long LL;
double mi[1 << 5], ma[1 << 5];
int main()
{
int n; scanf("%d", &n);
if(n == 1) { cout<<0; return 0; }
for(int i=0; i< 1<<5; i++) mi[i] = 9e18, ma[i] = -9e18;
while(n--)
{
double a, b, c, d, e; scanf("%lf %lf %lf %lf %lf", &a, &b, &c, &d, &e);
for(int i=0; i< 1<<5; i++)
{
double sum = ((i & 1) ? a : -a) + ((i >> 1 & 1) ? b : -b) + ((i >> 2 & 1) ? c : -c) + ((i >> 3 & 1) ? d : -d) + ((i >> 4 & 1) ? e : -e);
mi[i] = min(mi[i], sum);
ma[i] = max(ma[i], sum);
}
}
double ans = 0;
for(int i=0; i< 1<<5; i++) ans = max(ans, ma[i] - mi[i]);
printf("%.2f", ans);
return 0;
}
【多维曼哈顿最近点对】2019牛客第八场多校 D_Distance 三维BIT
题目:https://blog.csdn.net/weixin_42757232/article/details/99306935
题解:- https://blog.csdn.net/weixin_42757232/article/details/99306935
思路:
-
对于二维:
-
我们用以前的思路发现,查询时ans为
a n s = m i n ( m a x { ( x + y ) − ( x j + y j ) ( x − y ) − ( x j − y j ) ( − x + y ) − ( − x j + y j ) ( − x − y ) − ( − x j − y j ) } , m a x ( . . . . . . ) , . . . . . . ) (2) ans=min(max\left\{\begin{matrix}(x+y)-(x_j+y_j)\\ (x-y)-(x_j-y_j)\\ (-x+y)-(-x_j+y_j)\\ (-x-y)-(-x_j-y_j) \end{matrix} \right\} \tag{2} ,max(......),...... ) ans=min(max⎩⎪⎪⎨⎪⎪⎧(x+y)−(xj+yj)(x−y)−(xj−yj)(−x+y)−(−xj+yj)(−x−y)−(−xj−yj)⎭⎪⎪⎬⎪⎪⎫,max(......),......)(2) -
这样的式子,max没发现以前那样拆开,难以往下推。
-
如果像以前描的话,我们算出来的是每一行的max然后取min,不能保证和此式子等价。
正解:
- 以查询点为原点,将空间分隔为八个卦限,最优解一定存在于某个卦限。我们可以以这个立体空间的8个角分别为原点坐标建立8个三维树状数组,树状数组维护前缀最大值。那么我们如果要得到最近的点,我们就去八个树状数组中查询小于等于当前值的最大值,做差取最小值即可。
代码(拍了3000次):
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e7+100;
typedef long long LL;
int h1, h2, h3;
const int inf = 1e9;
int lowbit(int x) { return x & -x; }
int gethash(int x, int y, int z) { return (2 * h2 + 2) * (2 * h3 + 2) * x + (2 * h3 + 2) * y + z; } // 数据强制hash
struct node{
int ma[N];
void init(){
for(int i=0; i<N; i++) ma[i] = -inf;
}
int query(int x, int y, int z){
int res = -inf;
for(int i=x; i>=1; i-=lowbit(i))
for(int j=y; j>=1; j-=lowbit(j))
for(int k=z; k>=1; k-=lowbit(k))
res = max(res, ma[gethash(i, j, k)]);
return res;
}
void modify(int x, int y, int z){
for(int i=x; i<2 * h1 + 3; i+=lowbit(i))
for(int j=y; j< 2 * h2 + 3; j+=lowbit(j))
for(int k=z; k< 2 * h3 + 3; k+=lowbit(k))
ma[gethash(i, j, k)] = max(ma[gethash(i, j, k)], x + y + z);
}
}BIT[8];
int main()
{
int n; scanf("%d %d %d %d",&h1, &h2, &h3, &n);
int op, x, y, z;
for(int i=0; i<8; i++) BIT[i].init();
while(n--)
{
scanf("%d %d %d %d", &op, &x, &y, &z);
if(op == 1){
for(int i=0; i< 1 << 3; i++)
{
int xx = h1 + 1 + ((i & 1) ? x : -x), yy = h2 + 1 + ((i >> 1 & 1) ? y : -y), zz = h3 + 1 + ((i >> 2 & 1) ? z : -z);
BIT[i].modify(xx, yy, zz);
}
}else{
int ans = inf;
for(int i=0; i< 1 << 3; i++)
{
int xx = h1 + 1 + ((i & 1) ? x : -x), yy = h2 + 1 + ((i >> 1 & 1) ? y : -y), zz = h3 + 1 + ((i >> 2 & 1) ? z : -z);
int sum = xx + yy + zz;
int res = BIT[i].query(xx, yy, zz);
ans = min(sum - res, ans);
}
printf("%d\n", ans);
}
}
system("pause");
return 0;
}