题意:在一条数轴上有若干'R','B',‘G'点,连接两个点的代价是位置差,要求使用最小代价使得除去所有'R'点后剩下的所有点联通,除去所有'B'点后剩下的所有点联通。
还以为会是什么最小生成树,结果是脑洞题啊
因为G点总是要保留下来的,所以考虑按照G分成若干块,对于每个以G开头以G结尾的块,考虑如下两种操作:
1.分别依次连接 左G—中间所有的R—右G、左G—中间所有的B—右G,代价为 $ 2*len $
2.连接两端的G,再由两端的G依次分别连接中间的B和R,即,把两端的G和R、B分别依次连接,然后分别断掉最长的一段,代价为 $ 3*len-mxb-mxr $
对于每个区间分别求一下两个情况去min即可,复杂度 $ O(n) $
注意:
1.没有G的情况
2.一个区间内没有B或R的情况
#include<iostream>
#include<cstdio>
using namespace std;
const int N=300005;
int n,d[N],tot,ans;
char s[10];
struct qwe
{
int p;
char c;
}a[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%s",&a[i].p,s);
a[i].c=s[0];
if(s[0]=='G')
d[++tot]=i;
}
if(!tot)
d[1]=n+1;
for(int i=1;i<d[1];i++)
if(a[i].c=='R')
{
ans+=a[d[1]].p-a[i].p;
break;
}
for(int i=1;i<d[1];i++)
if(a[i].c=='B')
{
ans+=a[d[1]].p-a[i].p;
break;
}
for(int i=n;i>d[tot];i--)
if(a[i].c=='R')
{
ans+=a[i].p-a[d[tot]].p;
break;
}
for(int i=n;i>d[tot];i--)
if(a[i].c=='B')
{
ans+=a[i].p-a[d[tot]].p;
break;
}
for(int i=1;i<tot;i++)
{
int prr=a[d[i]].p,prb=a[d[i]].p,mxr=0,mxb=0,len=a[d[i+1]].p-a[d[i]].p;
for(int j=d[i]+1;j<d[i+1];j++)
if(a[j].c=='R')
{
mxr=max(mxr,a[j].p-prr);
prr=a[j].p;
}
for(int j=d[i]+1;j<d[i+1];j++)
if(a[j].c=='B')
{
mxb=max(mxb,a[j].p-prb);
prb=a[j].p;
}
if(prr!=a[d[i]].p)
mxr=max(mxr,a[d[i+1]].p-prr);
if(prb!=a[d[i]].p)
mxb=max(mxb,a[d[i+1]].p-prb);
ans+=min(2*len,(1+(mxb!=0)+(mxr!=0))*len-mxr-mxb);
}
cout<<ans<<endl;
return 0;
}