zoukankan      html  css  js  c++  java
  • bzoj1604 / P2906 [USACO08OPEN]牛的街区Cow Neighborhoods

    P2906 [USACO08OPEN]牛的街区Cow Neighborhoods

    考虑维护曼哈顿距离:$left | x_{1}-x_{2} ight |+left | y_{1}-y_{2} ight |$

    看起来很难维护的样子,我们尝试转化

    设两个点$(x_{1},y_{1}),(x_{2},y_{2})  (x_{1}>=x_{2})$

    那么它们的曼哈顿距离有2种情况

    1.$y_{1}>y_{2}:left | x_{1}-x_{2} ight |+left | y_{1}-y_{2} ight |=x_{1}-x_{2}+y_{1}-y_{2}=(x_{1}+y_{1})-(x_{2}+y_{2})$

    2.$y_{1}<y_{2}:left | x_{1}-x_{2} ight |+left | y_{1}-y_{2} ight |=x_{1}-x_{2}-y_{1}+y_{2}=(x_{1}-y_{1})-(x_{2}-y_{2})$

    于是我们就可以转为维护$(X=x+y,Y=x-y)$

    这样曼哈顿距离就愉快地转化为$max(X_{1}-X_{2},Y_{1}-Y_{2})$了

    我们先把所有坐标按$x$升序排一遍。

    蓝后$x$坐标用一个队列维护

    $y$坐标则用$multiset$维护(当然你愿意的话也可以打个平衡树(逃))

    每次在$multiset$里搞搞啥$lower\_bound$操作就行了。

    至于点的联通问题,搞一个并查集

    end.

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #define re register
    using namespace std;
    typedef long long ll;
    void read(ll &x){
        char c=getchar();x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    }
    int max(int &a,int &b){return a>b?a:b;}
    #define N 100002
    struct data{
        ll x,y;int id;
        data(){}
        data(ll A,ll B,int C):
            x(A),y(B),id(C)
        {}
        bool operator < (const data &tmp) const{return y<tmp.y;}
    }a[N];
    bool cmp(const data &A,const data &B){return A.x<B.x;}
    multiset <data> s;
    int n,t,mxd=-1e9,fa[N],siz[N]; ll c;
    int found(int x){return fa[x]==x?x:fa[x]=found(fa[x]);}
    void uni(int x,int y){
        int r1=found(x),r2=found(y);
        if(r1!=r2){
            siz[r1]+=siz[r2]; --t;
            siz[r2]=0; fa[r2]=r1;
        }
    }
    int main(){
        scanf("%d",&n); read(c); t=n; ll q1,q2;
        for(re int i=1;i<=n;++i){
            read(q1); read(q2);
            fa[i]=i; siz[i]=1;
            a[i]=data(q1+q2,q1-q2,i);
        }sort(a+1,a+n+1,cmp);
        s.insert(data(0,1e16,0));
        s.insert(data(0,-1e16,0));//添加边界防止指针越界
        s.insert(a[1]); int hd=1;
        multiset<data>::iterator it;
        for(re int i=2;i<=n;++i){
            while(a[hd].x+c<a[i].x) s.erase(s.find(a[hd++]));//队列维护
            it=s.lower_bound(a[i]);//找到第一个>=a[i].y的
            if((*it).y-a[i].y<=c) uni((*it).id,a[i].id);
            if(a[i].y-(*(--it)).y<=c) uni((*it).id,a[i].id);
            s.insert(a[i]);
        }printf("%d ",t);
        for(re int i=1;i<=n;++i) mxd=max(mxd,siz[i]);
        printf("%d",mxd);
        return 0;
    }
  • 相关阅读:
    EasyUI dialog
    winform 收集
    ASP.NET文件下载,直接向客户端输出文件(转)
    反射收集
    Sql Server 2008 R2 备份数据库报错
    慎用Ext.QuickTip和Ext.QuickTips(转)
    使用正则Regex来移除网页的ViewState(转)
    mysql 实现远程链接(转)
    MySqlBackup.NET,C# mysql备份数据库
    Firefox下站长统计代码不起作用
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9853281.html
Copyright © 2011-2022 走看看