[arc065e]Manhattan Compass

来源:互联网 发布:sql查询sequence 编辑:程序博客网 时间:2024/06/05 20:59

题目大意

不想讲。

做法

可以转45度角变成切比雪夫距离,这样图像是正方形。
先用bfs找出所有可以踩到的点(可以对每行每列维护set,一个被bfs到的直接在两颗平衡树中删去)。
然后对每个能被踩到的点统计与其切比雪夫距离为d的点的个数(可以对每行每列维护vector并二分)。
最后答案除以2。

#include<cstdio>#include<algorithm>#include<cmath>#include<set>#include<map>#include<vector>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=100000+10;const ll inf=40000000000;map<ll,int> row,col;struct dong{    int id,y;    ll x;    friend bool operator <(dong a,dong b){        return a.x<b.x||a.x==b.x&&a.id<b.id;    }} zlt;set<dong> ro[maxn],co[maxn];set<dong>::iterator it;vector<dong> rw[maxn],cl[maxn];vector<dong>::iterator ti;int x[maxn],y[maxn],dl[maxn];ll p[maxn],q[maxn];bool bz[maxn];int i,j,k,l,t,n,m,xx,yy,a,b,head,tail,now,tot,top;ll ans,d;void del(int id){    int xx=x[id],yy=y[id];    zlt.id=id;zlt.x=q[yy];    ro[xx].erase(ro[xx].find(zlt));    zlt.id=id;zlt.x=p[xx];    co[yy].erase(co[yy].find(zlt));}void ins(int x,ll l,ll r){    int y;    dong wxh;    while (1){        wxh.id=0;wxh.x=l;        it=ro[x].lower_bound(wxh);        if (it==ro[x].end()) break;        zlt=*it;        if (zlt.x>r) break;        y=zlt.id;        bz[y]=1;        dl[++tail]=y;        del(y);    }}void inse(int x,ll l,ll r){    int y;    dong wxh;    while (1){        wxh.id=0;wxh.x=l;        it=co[x].lower_bound(wxh);        if (it==co[x].end()) break;        zlt=*it;        if (zlt.x>r) break;        y=zlt.id;        bz[y]=1;        dl[++tail]=y;        del(y);    }}void ask(int x,ll l,ll r){    /*int t=lower_bound(rw[x],rw[x]+s,r+1)-rw[x];    t-=lower_bound(rw[x],rw[x]+s,l)-rw[x];*/    dong wxh;    wxh.id=0;wxh.x=r+1;    zlt=*(lower_bound(rw[x].begin(),rw[x].end(),wxh));    int t=zlt.y;    wxh.id=0;wxh.x=l;    zlt=*(lower_bound(rw[x].begin(),rw[x].end(),wxh));    t-=zlt.y;    ans+=(ll)t;}void query(int x,ll l,ll r){    /*int s=cl[x].size();    int t=lower_bound(cl[x],cl[x]+s,r+1)-cl[x];    t-=lower_bound(cl[x],cl[x]+s,l)-cl[x];    ans+=(ll)t;*/    dong wxh;    wxh.id=0;wxh.x=r+1;    zlt=*(lower_bound(cl[x].begin(),cl[x].end(),wxh));    int t=zlt.y;    wxh.id=0;wxh.x=l;    zlt=*(lower_bound(cl[x].begin(),cl[x].end(),wxh));    t-=zlt.y;    ans+=(ll)t;}int main(){    scanf("%d%d%d",&n,&a,&b);    fo(i,1,n){        scanf("%d%d",&j,&k);        p[i]=x[i]=j-k;        q[i]=y[i]=j+k;    }    sort(p+1,p+n+1);    tot=unique(p+1,p+n+1)-p-1;    fo(i,1,n) x[i]=lower_bound(p+1,p+tot+1,x[i])-p;    sort(q+1,q+n+1);    top=unique(q+1,q+n+1)-q-1;    fo(i,1,n) y[i]=lower_bound(q+1,q+top+1,y[i])-q;    fo(i,1,tot) row[p[i]]=i;    fo(i,1,top) col[q[i]]=i;    d=max(abs(p[x[a]]-p[x[b]]),abs(q[y[a]]-q[y[b]]));    fo(i,1,n){        zlt.id=i;zlt.x=q[y[i]];        ro[x[i]].insert(zlt);        rw[x[i]].push_back(zlt);        zlt.id=i;zlt.x=p[x[i]];        co[y[i]].insert(zlt);        cl[y[i]].push_back(zlt);        /*rw[x[i]].push_back(q[y[i]]);        cl[y[i]].push_back(p[x[i]]);*/    }    fo(i,1,tot){        sort(rw[i].begin(),rw[i].end());        zlt.id=0;zlt.x=inf;        rw[i].push_back(zlt);        t=rw[i].size();        fo(j,0,t-1) rw[i][j].y=j;    }    fo(i,1,top){        sort(cl[i].begin(),cl[i].end());        zlt.id=0;zlt.x=inf;        cl[i].push_back(zlt);        t=cl[i].size();        fo(j,0,t-1) cl[i][j].y=j;    }    head=0;    dl[tail=1]=a;    bz[a]=1;    del(a);    while (head<tail){        now=dl[++head];        xx=x[now];yy=y[now];        if (row[p[xx]-d]) ins(row[p[xx]-d],q[yy]-d,q[yy]+d);        if (row[p[xx]+d]) ins(row[p[xx]+d],q[yy]-d,q[yy]+d);        if (col[q[yy]-d]) inse(col[q[yy]-d],p[xx]-d,p[xx]+d);        if (col[q[yy]+d]) inse(col[q[yy]+d],p[xx]-d,p[xx]+d);    }    fo(i,1,n)        if (bz[i]){            xx=x[i];yy=y[i];            if (row[p[xx]-d]) ask(row[p[xx]-d],q[yy]-d+1,q[yy]+d);            if (col[q[yy]-d]) query(col[q[yy]-d],p[xx]-d,p[xx]+d-1);            if (row[p[xx]+d]) ask(row[p[xx]+d],q[yy]-d,q[yy]+d-1);            if (col[q[yy]+d]) query(col[q[yy]+d],p[xx]-d+1,p[xx]+d);        }    ans/=2;    printf("%lld\n",ans);}