CF1651D Nearest Excluded Points
传送门
题意
给出 个坐标轴上的点,把他们标记, 每次询问一个 , 求与该点曼哈顿距离最近的没有被标记的点
题解
不太难, 就用暴力做法了
考虑到一个点到它最近的非标记点的路径,不会同时存在向右和向左, 也不会同时存在向上向下
假如限制只能向下和向右走的话,那么显然可以dp且没有后效性, 如果存在一个答案在右下方,那么这样dp是对的
不然的话,答案要么在左上,要么左下, 要么右上,4遍记忆化即可
看似暴力,实际理论复杂度, 虽然我常数及其大, 哦不对我摆烂用了map,寄!
实现
考场暴力代码
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
int read(){
int num=0, flag=1; char c=getchar();
while(!isdigit(c) && c!='-') c=getchar();
if(c == '-') c=getchar(), flag=-1;
while(isdigit(c)) num=num*10+c-'0', c=getchar();
return num*flag;
}
const int N = 5000005;
int T, n, m;
int X[N], Y[N];
map<int, map<int, int> > d;
map<int, map<int, int> > id;
map<int, map<int, int> > f1;
map<int, map<int, int> > f2;
map<int, map<int, int> > f3;
map<int, map<int, int> > f4;
int abss(int x){return x>=0?x:-x;}
int dis(int a, int b){
return abss(X[a]-X[b]) + abss(Y[a]-Y[b]);
}
int solve1(int x, int y){
if(!id[x][y]) {
id[x][y] = ++m;
X[m]=x;
Y[m]=y;
}
if(!d[x][y]) return id[x][y];
if(f1[x][y]) return f1[x][y];
int r1 = solve1(x+1, y);
int r2 = solve1(x, y-1);
if(dis(id[x][y], r1) <= dis(id[x][y], r2)) f1[x][y]=r1;
else f1[x][y]=r2;
return f1[x][y];
}
int solve2(int x, int y){
if(!id[x][y]) {
id[x][y] = ++m;
X[m]=x;
Y[m]=y;
}
if(!d[x][y]) return id[x][y];
if(f2[x][y]) return f2[x][y];
int r1 = solve2(x-1, y);
int r2 = solve2(x, y+1);
if(dis(id[x][y], r1) <= dis(id[x][y], r2)) f2[x][y]=r1;
else f2[x][y]=r2;
return f2[x][y];
}
int solve3(int x, int y){
if(!id[x][y]) {
id[x][y] = ++m;
X[m]=x;
Y[m]=y;
}
if(!d[x][y]) return id[x][y];
if(f3[x][y]) return f3[x][y];
int r1 = solve3(x+1, y);
int r2 = solve3(x, y+1);
if(dis(id[x][y], r1) <= dis(id[x][y], r2)) f3[x][y]=r1;
else f3[x][y]=r2;
return f3[x][y];
}
int solve4(int x, int y){
if(!id[x][y]) {
id[x][y] = ++m;
X[m]=x;
Y[m]=y;
}
if(!d[x][y]) return id[x][y];
if(f4[x][y]) return f4[x][y];
int r1 = solve4(x-1, y);
int r2 = solve4(x, y-1);
if(dis(id[x][y], r1) <= dis(id[x][y], r2)) f4[x][y]=r1;
else f4[x][y]=r2;
return f4[x][y];
}
int get(int x, int r1, int r2, int r3, int r4){
if(dis(x, r1)<=dis(x, r2) && dis(x, r1)<=dis(x, r3) && dis(x, r1)<=dis(x, r4)) return r1;
else if(dis(x, r2)<=dis(x, r3) && dis(x, r2)<=dis(x, r4)) return r2;
else if(dis(x, r3)<=dis(x, r4)) return r3;
else return r4;
}
int main(){
m = n = read();
for(int i=1; i<=n; i++) {
X[i]=read(), Y[i]=read();
d[X[i]][Y[i]]=1;
id[X[i]][Y[i]]=i;
}
for(int i=1; i<=n; i++){
int r1 = solve1(X[i], Y[i]);
int r2 = solve2(X[i], Y[i]);
int r3 = solve3(X[i], Y[i]);
int r4 = solve4(X[i], Y[i]);
int x = get(i, r1, r2, r3, r4);
printf("%d %d\n", X[x], Y[x]);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现