• Jzoj1973 信号塔


      lanwuni接到一个任务,在C市建立N个信号塔来完成城市中的通讯任务。   

    假设C市是一个坐标范围[-2000000,2000000]的网格,一些整点上有用户,你也可以在整点上建立信号塔。

    一个点上可以建立多座。 在C市,两点之间的距离是曼哈顿距离,也就是横纵坐标差值之和。

    每个信号塔都有一个半径Di,表示与i曼哈顿距离不超过Di的地方都能被这个信号塔的信号覆盖到。  

    建立信号塔要满足一些性质:

       1. 每个信号塔有一定的用户,lanwuni要把信号塔建立在某个地方,使得属于该塔的用户都能被信号覆盖到;

       2. 信号塔有一定等级和安装限制,所以,第i号信号塔能覆盖的所有整点,必须也被第i+1号信号塔覆盖到。即使这个整点上没有用户。   

    现在告诉你每个信号塔的半径,以及每个信号塔的用户,请你帮lanwuni谋划一下应该把这N个信号塔建立在什么地方,保证有解。


    非常好的计算几何

    首先,显然一个信号塔的范围是多个菱形的交,最后是一个平行四边形

    但是直接并起来非常不方便,因为斜着的平行四边形不好直接求交

    我们将其旋转π/4并乘上√2变成整数运算,那么坐标就变成了(X-Y,X+Y)

    变换完之后,每个信号塔的范围就是用户的范围交起来,让后根据半径的差值来倒序确定每个灯塔的范围,到1的时候随便选一个点作为答案

    注意:坐标的逆变换公式为(X+Y/2,-X+Y/2)所以要考虑奇偶性,做一些微调即可

    (这种题就是这么恶心,很难讲清楚,还是靠自己意会比较重要,有Solution也不是很清楚)

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 100010
    using namespace std;
    int x[N],y[N],n,m,r[N];
    struct mat{ int x[2],y[2]; } s[N],w[N];
    inline mat merge(mat a,mat b){
    	mat c;
    	c.x[0]=max(a.x[0],b.x[0]);
    	c.x[1]=min(a.x[1],b.x[1]);
    	c.y[0]=max(a.y[0],b.y[0]);
    	c.y[1]=min(a.y[1],b.y[1]);
    	return c;
    }
    inline mat out(mat x){
    	if(x.x[0]-x.y[0]&1)
    		if(x.x[0]<x.x[1]) ++x.x[0];
    		else ++x.y[0];
    	printf("%d %d
    ",x.x[0]+x.y[0]>>1,-x.x[0]+x.y[0]>>1);
    	return x;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",r+i);
    		s[i].x[0]=s[i].y[0]=-1e8;
    		s[i].x[1]=s[i].y[1]=+1e8;
    	}
    	for(int i=1,j,c;i<=n;++i){
    		scanf("%d%d%d",&j,x+i,y+i);
    		c=x[i]-y[i]; y[i]+=x[i]; x[i]=c;
    		s[j]=merge(s[j],(mat){{x[i]-r[j],x[i]+r[j]},{y[i]-r[j],y[i]+r[j]}});
    	}
    	w[n]=s[n];
    	for(int dr,i=n-1;i;--i){
    		w[i]=w[i+1];
    		dr=r[i+1]-r[i];
    		w[i].x[0]-=dr;
    		w[i].x[1]+=dr;
    		w[i].y[0]-=dr;
    		w[i].y[1]+=dr;
    		w[i]=merge(w[i],s[i]);
    	}
    	for(int dr,i=1;i<=n;++i){
    		s[i]=out(w[i]);
    		dr=r[i+1]-r[i];
    		w[i].x[0]=s[i].x[0]-dr;
    		w[i].x[1]=s[i].x[0]+dr;
    		w[i].y[0]=s[i].y[0]-dr;
    		w[i].y[1]=s[i].y[0]+dr;
    		w[i+1]=merge(w[i],w[i+1]);
    	}
    }
  • 相关阅读:
    第十周学习进度
    第九周学习进度
    冲刺阶段站立会议每日任务10
    冲刺阶段站立会议每日任务9
    冲刺阶段站立会议每日任务8
    冲刺阶段站立会议每日任务7
    第八周学习进度
    对输入法的评价
    冲刺阶段站立会议每日任务6
    冲刺阶段站立会议每日任务5
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477148.html
Copyright © 2020-2023  润新知