题意:
数轴上有三种类型的点:B型点、R型点、P型点。
你可以连接任意两个点,连接的代价是两个点的距离,即坐标之差。
而最终希望达到的条件是:
如果去除所有B型点,R型点和P型点中任意两个点连通。
如果去除所有R型点,B型点和P型点中任意两个点连通。
现在给定n个点的坐标和类型,求满足条件的最小代价。
思路:
首先有一个显然合法的可行方案:
即先单独考虑所有B型点和P型点,相邻的两个点连边,最终代价为最右边的点(B/P)和最左边的点(B/P)的距离。
随后单独考虑所有R型点和P型点,分析同上。
可是考虑一个特殊情况,有四个点,从左到右的坐标及类型为:
P(0) 、 B(1) 、 R(99) 、 P(100)
对于上面的方案,代价显然是: $Ans = (100-0) + (100-0) = 200 $
而更好的选择是:将两个P点连接起来,随后B点连接左边的P点,R点连接右边的P点,此时代价为:
A
n
s
=
(
100
−
0
)
+
(
1
−
0
)
+
(
100
−
99
)
=
102
Ans = (100-0) + (1-0) + (100-99) = 102
Ans=(100−0)+(1−0)+(100−99)=102
可以发现:
如果将两个相邻的P点连接起来,从而B型点和R型点连接时均可以共用这一条边,此时可能会让总代价变得更小。
故我们可以先按第一个方案算出一个初步的总代价
A
n
s
Ans
Ans
随后按坐标从左到右枚举两个相邻的P点:
而对于原来按第一种方案连接的结构,比如当考虑B型点和P型点时,连接是:
P
0
−
B
0
−
B
1
−
B
2
−
.
.
.
−
B
t
−
P
1
P_0 - B_0 - B_1 - B_2 - ... - B_t - P_1
P0−B0−B1−B2−...−Bt−P1
而此时因为 P 0 P_0 P0和 P 1 P_1 P1已经连接,故中间有一条边可以断开不连,由贪心的思想显然断开的边越长越好,假设对于该情况,断开的边最长长度为 F u n ( B ) Fun(B) Fun(B)
同理,可以求出 F u n ( R ) Fun(R) Fun(R)
则对于两个相邻P点构成的子区间,此时需要付出的总代价为:(假设
L
e
n
=
P
1
−
P
0
Len = P_1 - P_0
Len=P1−P0)
S
u
m
1
=
L
e
n
+
(
L
e
n
−
F
u
n
(
B
)
)
+
(
L
e
n
−
F
u
n
(
R
)
)
=
3
L
e
n
−
F
u
n
(
B
)
−
F
u
n
(
R
)
Sum1 = Len + (Len - Fun(B)) + (Len - Fun(R)) = 3Len - Fun(B) - Fun(R)
Sum1=Len+(Len−Fun(B))+(Len−Fun(R))=3Len−Fun(B)−Fun(R)
而原来需要付出的总代价为:
S
u
m
2
=
L
e
n
+
L
e
n
=
2
L
e
n
Sum2 = Len + Len = 2Len
Sum2=Len+Len=2Len
故对于原来得到的初步总代价
A
n
s
Ans
Ans,我们可以更新为:
A
n
s
−
=
S
u
m
2
−
S
u
m
1
Ans -= Sum2 - Sum1
Ans−=Sum2−Sum1
此题得解。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
char s[100+10];
vector<int> vR,vB,vP;
ll Fun(const vector<int>& v,int l,int r){
int st = lower_bound(v.begin(),v.end(),l) - v.begin();
int ed = lower_bound(v.begin(),v.end(),r) - v.begin();
ll res = 0;
for(int i=st ;i<ed ;i++) res = max(res,1LL*v[i+1]-1LL*v[i]);
return res;
}
int main(){
int n;scanf("%d",&n);
for(int i=1 ;i<=n ;i++){
int x;
scanf("%d%s",&x,s);
if(s[0] == 'R') vR.push_back(x);
else if(s[0] == 'B') vB.push_back(x);
else{
vR.push_back(x);
vB.push_back(x);
vP.push_back(x);
}
}
sort(vR.begin(),vR.end());
sort(vB.begin(),vB.end());
sort(vP.begin(),vP.end());
ll ans = 0;
if(vR.size() > 1) ans += vR[vR.size()-1] - vR[0];
if(vB.size() > 1) ans += vB[vB.size()-1] - vB[0];
int Siz = vP.size();
for(int i=0 ;i<Siz-1 ;i++){
int l = vP[i],r = vP[i+1];
ans -= max(0LL,Fun(vB,l,r) + Fun(vR,l,r) - 1LL*(r-l));
}
printf("%I64d\n",ans);
return 0;
}