CF1651D Nearest Excluded Points

传送门

题意

给出 \(n\) 个坐标轴上的点,把他们标记, 每次询问一个 \((x, y)\), 求与该点曼哈顿距离最近的没有被标记的点

题解

不太难, 就用暴力做法了
考虑到一个点到它最近的非标记点的路径,不会同时存在向右和向左, 也不会同时存在向上向下
假如限制只能向下和向右走的话,那么显然可以dp且没有后效性, 如果存在一个答案在右下方,那么这样dp是对的
不然的话,答案要么在左上,要么左下, 要么右上,4遍记忆化即可
看似暴力,实际理论复杂度\(O(n)\), 虽然我常数及其大, 哦不对我摆烂用了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;
}


posted @ 2022-03-15 11:38  ltdJcoder  阅读(48)  评论(0编辑  收藏  举报