P6751 [IOI2019]视觉程序 题解--zhengjun

提供一种简介易懂的做法。

首先曼哈顿距离的绝对值比较难处理,所以可以转成切比雪夫距离。

具体地说,就是 \((x,y)\) 变成 \((x+y,x-y)\)(接下来所述的坐标都是变换后的)。

这样 \((x,y),(a,b)\) 之间的距离就是 \(\max\{|a-x|,|b-y|\}\)

虽然这里还有绝对值,但是这个我们其实是知道大小的,所以并不影响。

接下来考虑怎么构造方案。

由于现在的距离带着 \(\max\),所以考虑判断两点间距离是否 \(\ge d\)

也就是 \(a-x\ge d\)\(b-y\ge d\),两维分开考虑,这里以 \(x\) 一维为例;

若枚举 \(x\),则只需判断是否存在 \(\ge x+d\)\(a\) 即可。

所以先用 \(O(n+m)\) 次查询,共 \(O(nm)\) 个数,统计出变换后的坐标有无黑点。

再做一次后缀和,然后就直接判断存在 \(\ge k\) 并且不存在 \(\ge k+1\) 即可。

代码

#include<bits/stdc++.h>
void construct_network(int H, int W, int K);
int add_and(std::vector<int> Ns);
int add_or(std::vector<int> Ns);
int add_xor(std::vector<int> Ns);
int add_not(int N);
using namespace std;const int N=2e2+10,M=N*2;
int n,m,k,a[M],b[M],c[M],d[M];vector<int>A[M],B[M];
int chk(int t){//判断两黑点距离是否 >= t 
	int x=add_or({add_and({a[0],c[t]}),add_and({b[0],d[t]})});
	for(int i=1;i+t<k;i++)x=add_or({x,add_and({a[i],c[i+t]})});
	for(int i=1;i+t<k;i++)x=add_or({x,add_and({b[i],d[i+t]})});
	return x;
}
void construct_network(int H,int W,int K){
	n=H;m=W;k=n+m-1;
	for(int i=0;i<n;i++)for(int j=0;j<m;j++)A[i+j].push_back(i*m+j);//切比雪夫坐标 
	for(int i=0;i<n;i++)for(int j=0;j<m;j++)B[i-j+m-1].push_back(i*m+j);
	for(int i=0;i<k;i++)a[i]=add_or(A[i]),b[i]=add_or(B[i]);
	c[k-1]=a[k-1];for(int i=k-2;i>=0;i--)c[i]=add_or({c[i+1],a[i]});//后缀 or 
	d[k-1]=b[k-1];for(int i=k-2;i>=0;i--)d[i]=add_or({d[i+1],b[i]});
	if(K<k-1)add_and({chk(K),add_not(chk(K+1))});else chk(K);
}
posted @ 2023-01-12 12:50  A_zjzj  阅读(30)  评论(0编辑  收藏  举报