zoukankan      html  css  js  c++  java
  • bzoj 1604

    前置技能:曼哈顿距离转切比雪夫距离

    曼哈顿距离:已知两点$A(x_{1},y_{1})$,$B(x_{2},y_{2})$,则其曼哈顿距离为$|x_{2}-x_{1}|+|y_{2}-y_{1}|$

    切比雪夫距离:已知两点$A(x_{1},y_{1})$,$B(x_{2},y_{2})$,则其切比雪夫距离为$max(|x_{2}-x_{1}|,|y_{2}-y_{1}|)$

    二者的转化:

    已知两点$A(x_{1},y_{1})$,$B(x_{2},y_{2})$,设$A^{'}(x_{1}+y_{1},x_{1}-y_{1})$,$B^{'}(x_{2}+y_{2},x_{2}-y_{2})$

    则$AB$两点的曼哈顿距离与$A^{'}B^{'}$之间的切比雪夫距离相等

    证明显然

    因此我们对每个点$P_{i}(x_{i},y_{i})$,构造一个新的点$P_{i}^{'}(x_{i}+y_{i},x_{i}-y_{i})$,这样我们只研究新点之间的切比雪夫距离即可

    为什么我们要这样做?

    这样的话我们就可以分别处理$x$和$y$了

    我们把所有的新点按照$x$进行排序,然后维护一个$set$里存原先的$y$

    从小向大枚举$x$,每枚举到一个$x$就先把之前x不合法的部分从set里删除,再在set里面查这个$y$的前驱后继,如果合法就连边(注意只想前驱后继连边即可,用并查集维护),再把y插入set中即可

    这样做的合理性在于,显然连的所有边都是合法的,而且根据传递性只需相邻的连边就能维护一个完整的集合了

    这样代码就很好写了

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #define ll long long
    using namespace std;
    struct node
    {
        ll x,y;
        friend bool operator < (node a,node b)
        {
            return a.x==b.x?a.y<b.y:a.x<b.x;
        }
    }p[100005];
    int n,C;
    int f[100005],siz[100005];
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    struct Info
    {
        ll y;
        int num;
        friend bool operator < (Info a,Info b)
        {
            return a.y==b.y?a.num<b.num:a.y<b.y;
        }
    };
    set <Info> S;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    void merge(int x,int y)
    {
        int f1=findf(x),f2=findf(y);
        if(f1!=f2)f[f2]=f1,siz[f1]+=siz[f2];
    }
    int main()
    {
        read(n),read(C);
        for(int i=1;i<=n;i++)
        {
            ll rx,ry;
            read(rx),read(ry);
            p[i].x=rx+ry,p[i].y=rx-ry;
            f[i]=i,siz[i]=1;
        }
        sort(p+1,p+n+1);
        int las=1;
        S.insert((Info){-0x3f3f3f3f3f3f3f3fll,0}),S.insert((Info){0x3f3f3f3f3f3f3f3fll,0});
        S.insert((Info){p[1].y,1});
        for(int i=2;i<=n;i++)
        {
            while(p[i].x-p[las].x>C&&las<i)S.erase((Info){p[las].y,las}),las++;
            set <Info>::iterator it1;
            it1=S.lower_bound((Info){p[i].y,0});
            if(it1!=S.end()&&abs(p[i].y-(*it1).y)<=C)merge(i,(*it1).num);
            it1--;
            if(it1!=S.end()&&abs(p[i].y-(*it1).y)<=C)merge(i,(*it1).num);
            S.insert((Info){p[i].y,i});
    
        }
        int cnt=0,ans=0;
        for(int i=1;i<=n;i++)if(f[i]==i)cnt++,ans=max(ans,siz[i]);
        printf("%d %d
    ",cnt,ans);
        return 0;
    }
  • 相关阅读:
    Python form...import...和import的区别(自己理解的)
    ! cocos2d 同一个sprite的触控问题
    cocosjs 触摸
    打包apk
    单例模式
    策略模式
    工厂模式
    cocos3 singleton
    tiledmap2
    quick cocos 暂停场景
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11082532.html
Copyright © 2011-2022 走看看