题目描述
T-net which is a new telecommunications company, plans to install its base stations in the city. The places where base stations must be installed have been already specified. T-net has two types of antennas to be used in the base stations: (i)antennas with transmission radius a, and (ii) antennas with transmission radius b. Two antennas can communicate with each other if and only if both are inside the coverage area of each other. Antenna with smaller transmission radius of course is cheaper. T-net plans to minimize its cost while keeping the whole network connected. Precisely, T-net plans to
minimize its cost which is the sum of the transmission radii of all antennas. Interestingly, all base-station places are on a line. Help T-net construct a connected network with the minimum cost.
译文:T-net是一个新的通讯公司,计划在城市里安装一些信号站,安装信号站的地方必须是早已指定的。T-net有两种天线可用于建造信号站:(i)信号半径为a的天线,(ii)信号半径为b的天线。两个天线是当且仅当两者各自的信号范围内的时候两条天线才能通讯。自然,半径较小的天线更便宜。T-net打算在维持整个工作网络连通的同时最小化花销。准确来说,T-net打算最小化的花销是各天线半径之和。有意思的是,所有信号站都在一条线上,帮助T-net用最小成本建立通讯网络。
输入
The first line of the input contains three positive integers n, a and b (1 ⩽ n ⩽ 105 and 1 ⩽ a, b ⩽ 105 ) where n is the number of base stations, and a and b are radii as defined in the problem statement. The second line contains n distinct coordinates of base stations on the line with respect to an origin on the line. All coordinates are positive integers not more than 105 .
译文:第一行输入三个正整数n,a,b, n是信号站个数,a和b是题目中所定义的半径。第二行的一行内包含n个信号站相对于原点的不同坐标。所有坐标都是105以内的正整数。
输出
If it is possible to construct a connected network, print the minimum cost in the output. Otherwise, print -1 .
译文:如果可能建设这样一个连通网络,输出最小花销,否则输出-1。
样例输入
复制样例数据
3 1 3
1 4 3
样例输出
7
可能看完题之后我们还是不明白何谓连通?研究一下样例发现:1 3 4三个坐标中,1安装半径为3的天线,4安装半径为3的天线,3安装半径为1的天线可以达成连通,这是因为1和4相互连通后,3同时在1和4信号范围之内,用最小的天线就可以达成网络连通,1+3+1为7。
所以就有一个贪心策略:设两个天线中范围最大的为b,则在两个b型信号站中的所有信号站只需要连接到最近的那个信号站即可,如果中间有信号站间距大于a,则必须选b,若选b,一切又要分左右区间讨论,详细的在代码中指出。
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cmath>
//#include <minmax.h>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
const double PI=acos(-1);
using namespace std;
typedef long long ll;
typedef long double ld;
const int MOD=998244353;
/**you can feel the pulse of your destiny...
The nervous feeling fills you with determination.**/
ll position[300044];
ll antennas[300044];
ll pointer2,pointer3;
ll j;
int DETERMINATION()
{
ll n,a,b;
cin>>n>>a>>b;
if(a>b)//不妨设a<=b
swap(a,b);
for(int i=1; i<=n; i++)
cin>>position[i];
sort(position+1,position+n+1);//位置沿x轴方向从小到大排序
position[0]=position[1];//扩展边界以防runtime error
position[n+1]=position[n];//同上
for(int i=1; i<=n; i++)
{
if(antennas[i])
continue;//如果这里装了天线,看下一个
if(position[i]-position[i-1]>b&&position[i+1]-position[i]>b)
{
cout<<-1<<endl;//有一个基站是两边加b型天线都抢救不了的,那这个网络不能建成
return 0;
}
if(position[i]-position[i-1]<=a&&position[i+1]-position[i]<=a)
{
antennas[i]=a;//连接两边只需要a天线的一类
continue;
}
antennas[i]=b;//假设这个地方安装b天线
while(antennas[i]==b)//当这个地方维持安装b天线不变时。
{
//cout<<"!"<<endl;
ll pointer=i;//定义指针1
while(pointer<=n)//找到当前位置加radius_b向前能够到最远的信号站
{
if(position[pointer]-position[i]>b)
break;
pointer++;
}
pointer--;//因为循环退出时指向了超出范围的第一个基站,所以回退一个
bool sign=false;
for(j=i+1;j<=pointer-1;j++)
{
if(position[j]-position[j-1]>a||position[j+1]-position[j]>a)
{
sign=true;//假如说这个区间【i,pointer】内的基站有一个及以上不是简单安装a就能完事的
break;
}
}
if(!sign)
break;//否则就break掉,在接下来的循环中直接装a
antennas[pointer]=b;//两个端点的b型天线把这个区间包裹起来
for(pointer2=i+1;pointer2<=pointer-1;pointer2++)
{
if(position[pointer2]-position[pointer2-1]<=a)
antennas[pointer2]=a;//向右遍历,如果有一个间距可以直接用a摆平,那么安装a天线
else
break;//否则把指针指向这个地方
}
for(pointer3=pointer-1;pointer3>=i+1;pointer3--)
{
if(antennas[pointer3])
break;//此位置已安装过
if(position[pointer3+1]-position[pointer3]<=a)
antennas[pointer3]=a;
else
break;//作用同上
}
while(pointer2<=pointer3)//最后的这个区间内部仍然有几个地方没有安装天线
{
antennas[pointer2]=b;//因为上边的指针是指向安装a摆平不了的地方,所以这个地方安装b
pointer2++;//前移
while(pointer2<=pointer3&&position[pointer2]-position[pointer2-1]<=a)
{
//假如当前这个与前一个的间距又可以用a连接了
antennas[pointer2++]=a;
}
}
i=pointer;//整个区间处理完毕,直接跳到区间末
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=antennas[i];
cout<<antennas[i]<<endl;
}
cout<<ans<<endl;
return 0;
}