题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12033
题意:给定一个n*m 的方格,num个污染源及坐标。(x,y)污染程度:min(max(|x-xi|, |y − yi|)),(xi,yi)表示污染源的坐标。现在对n*m-num个格子编号。首先按污染程度,x,y的优先级编号,越小编号越大。现在有q个询问,每次询问编号为k的坐标(x,y)
解题思路:三次二分,先二分k所对应的污染程度,对于确定的污染程度dis可以用矩形的面积并求出<=dis的有多少个。求出dis后在二分x,之后二分y,求出的x,y即为答案。
#include<iostream> #include<stdio.h> #define LL long long #define N 105 const LL inf=(LL)1e9+10; using namespace std; struct point{ LL x,y; point(LL x=0,LL y=0):x(x),y(y){} void read(){ cin>>x>>y; } }p[N]; struct rec { point p1,p2; rec(point _=point(),point __=point()):p1(_),p2(__){} rec(LL x1,LL y1,LL x2,LL y2):p1(point(x1,y1)),p2(point(x2,y2)){} void get(LL &x1,LL &y1,LL &x2,LL &y2){ x1=p1.x; y1=p1.y; x2=p2.x; y2=p2.y; } LL area(point p3=point(inf,inf)){ return (min(p2.x,p3.x)-min(p1.x,p3.x))*(min(p2.y,p3.y)-min(p1.y,p3.y)); } }r1[N],r2[N],tmp[N]; LL cnt1,cnt2,tcnt,n,m,num; inline void cut(rec a,rec b,rec r[],LL &cnt) {//其中点分别为矩形左下侧点和右上侧点 LL k1,k2,k3,k4,x1,x2,x3,x4,y1,y2,y3,y4; a.get(x1,y1,x2,y2); b.get(x3,y3,x4,y4); if(x2<=x3||y2<=y3||x4<=x1||y4<=y1){ r[cnt++]=rec(x1,y1,x2,y2);//如果不相交 return ; } k1=max(x1,x3);k2=min(x2,x4); if(x1<k1) r[cnt++]=rec(x1,y1,k1,y2); if(x2>k2) r[cnt++]=rec(k2,y1,x2,y2); k3=k1,k4=k2; k1=max(y1,y3);k2=min(y2,y4); if(y1<k1) r[cnt++]=rec(k3,y1,k4,k1); if(y2>k2) r[cnt++]=rec(k3,k2,k4,y2); } LL get_num(rec r[],LL cnt,point p=point(inf,inf)) { LL ret=0; for(int i=0;i<cnt;i++) ret=ret+r[i].area(p); return ret; } void get_rec(LL dis,rec r[],LL &cnt) { cnt=0; for(int i=0;i<num;i++) { for(int j=0;j<cnt;j++) tmp[j]=r[j]; tcnt=cnt; cnt=0; rec rr=rec(max(p[i].x-dis,1ll),max(p[i].y-dis,1ll),min(p[i].x+dis,n)+1,min(p[i].y+dis,m)+1); for(int j=0;j<tcnt;j++) cut(tmp[j],rr,r,cnt); r[cnt++]=rr; } } void solve(LL k) { LL x,y,l,r,mid; l=1; r=max(n,m); while(l<r){ mid=(l+r)/2; get_rec(mid,r1,cnt1); if(get_num(r1,cnt1)<k) l=mid+1; else r=mid; } get_rec(l,r1,cnt1); get_rec(l-1,r2,cnt2); k-=get_num(r2,cnt2); point p; l=1; r=n+1; while(l<r){ mid=(l+r)/2; p=point(mid,inf); if(get_num(r1,cnt1,p)-get_num(r2,cnt2,p)<k) l=mid+1; else r=mid; } x=l; l=1; r=m+1; p=point(x-1,inf); k-=(get_num(r1,cnt1,p)-get_num(r2,cnt2,p)); while(l<r){ mid=(l+r)/2; p=point(x,mid); LL tmp=get_num(r1,cnt1,p)-get_num(r2,cnt2,p); p=point(x-1,mid); tmp-=get_num(r1,cnt1,p)-get_num(r2,cnt2,p); if(tmp<k) l=mid+1; else r=mid; } y=l; cout<<x-1<<' '<<y-1<<endl; } int main() { // freopen("1.in","r",stdin); while(cin>>n>>m>>num,n+m+num) { for(int i=0;i<num;i++) p[i].read(); LL q,k; cin>>q; while(q--) { cin>>k; solve(k+num); } puts("-"); } }
// by oone #include <cstdio> #include <iostream> using namespace std; typedef long long LL; #define D 2 struct cube{ int s[D],e[D]; int type; cube(){} cube(cube &t,int m,int type):type(type){ for(int i=0;i<D;i++){ s[i]=t.s[i]-m; e[i]=t.e[i]+m; } } LL area(cube &t){ LL k=1; for(int i=0;i<D;i++) k*=(LL)(min(e[i],t.e[i])-max(s[i],t.s[i])); return k; } }p[30],big; cube c[1000],d[1000]; int q; struct CUT{ int cn,dn; void broke(cube &a,cube &b){ cube t; for(int i=0;i<D;i++){ if(b.s[i]>a.s[i]&&b.s[i]<a.e[i]){ t=a; t.e[i]=b.s[i]; d[dn++]=t; a.s[i]=b.s[i]; } if(b.e[i]>a.s[i]&&b.e[i]<a.e[i]){ t=a; t.s[i]=b.e[i]; d[dn++]=t; a.e[i]=b.e[i]; } } } bool check(cube &a,cube &b){ for(int i=0;i<D;i++) if(a.s[i]>=b.e[i]||b.s[i]>=a.e[i])return 0; return 1; } void insert(cube &t){ dn=0; for(int i=0;i<cn;i++){ if(check(c[i],t))broke(c[i],t); else d[dn++]=c[i]; } cn=0; c[cn++]=t; for(int i=0;i<dn;i++)c[cn++]=d[i]; } void push(int m,int type){ for(int i=0;i<q;i++){ cube t(p[i],m,type); insert(t); } } LL area(cube &t){ LL ans=0; for(int i=0;i<cn;i++) if(check(c[i],t))ans+=c[i].area(t); return ans; } void refush(){ int n=0; for(int i=0;i<cn;i++) if(c[i].type)c[n++]=c[i]; cn=n; } }cut; void solve(){ LL n; cin>>n; int l=0,r=max(big.e[0],big.e[1]); while(l<r){ cut.cn=0; int m=(l+r)>>1; cut.push(m,1); if(cut.area(big)-q<n)l=m+1; else r=m; } cut.cn=0; cut.push(l-1,1); n-=(cut.area(big)-q); cut.cn=0; cut.push(l,1); cut.push(l-1,0); cut.refush(); cube res=big; l=0,r=big.e[1]; while(l<r){ res.e[1]=(l+r)>>1; if(cut.area(res)<n)l=res.e[1]+1; else r=res.e[1]; } res.e[1]=l-1; n-=cut.area(res); res.s[1]=l-1; res.e[1]=l; l=0,r=big.e[0]; while(l<r){ res.e[0]=(l+r)>>1; if(cut.area(res)<n)l=res.e[0]+1; else r=res.e[0]; } printf("%d %d\n",res.e[1],l); } int main(){ while(scanf("%d%d%d",&big.e[1],&big.e[0],&q),big.e[0]||big.e[1]||q){ big.s[0]=big.s[1]=0; for(int i=0;i<q;i++){ for(int j=D-1;j>=0;j--){ scanf("%d",&p[i].e[j]); p[i].s[j]=p[i].e[j]-1; } } int Q; scanf("%d",&Q); while(Q--)solve(); puts("-"); } return 0; }