这题调了我3小时…
显然只选相邻的两个楼,因为线路之间不能相交(比如说(1,3),(2,4)可以优化为(1,2)(3,4))所以如果选了(1,4)那么1和4之间的点都不会被用到(不然一定和(1,4)相交)而(1,2)肯定比(1,4)短,这么一来只选相邻
a_i表示第i个楼与第i+1个楼的距离设i时a_i取最小时的i 根据题意选了a_i就不能选a_(i-1),a_(i+1) 所以在选了a_i后删去a_i,a_i-1,a_i+1并加入a_(i+1)+a_(i-1)-a_i,如果后面选了新加的就表示不应选a_i而应a_(i-1)和a_(i+1),因为a_i最小所以旁边两个要么同时选要么同时不选
边界要特殊考虑 如果1比2小就直接确定选2不选1 因为选了2以后能选到的选了1也都能选到
代码
#include<iostream>
#include<cstdio>
using namespace std;
int n,k;
int prv[100005],nxt[100005],pos[100005];
struct node
{
int v,x;
}h[100005];
int tot;
void up(int p)
{
while(p>1)
{
if(h[p>>1].v>h[p].v)
{
pos[h[p>>1].x]=p;
swap(h[p>>1],h[p]);
p>>=1;
}else break;
}
pos[h[p].x]=p;
}
void down(int p)
{
int s=2*p;
while(s<=tot)
{
if(s<tot&&h[s+1].v<h[s].v)++s;
if(h[p].v>h[s].v)
{
pos[h[s].x]=p;
swap(h[p],h[s]);
p=s;
s=2*p;
}else break;
}
pos[h[p].x]=p;
}
void inst(int x,int y)
{
h[++tot].v=x;
h[tot].x=y;
up(tot);
}
void rmov(int p)
{
h[p].v=2e9;
down(p);
}
int main()
{
scanf("%d%d",&n,&k);
int u,v;
scanf("%d",&u);
for(int i=1;i<n;++i)
{
scanf("%d",&v);
prv[i]=i-1,nxt[i]=i+1;
inst(v-u,i);
u=v;
}
int ans=0;
for(int i=1;i<=k;++i)
{
ans+=h[1].v;
int t=h[1].x;
if(prv[t]==0)
{
rmov(1);
rmov(pos[nxt[t]]);
prv[nxt[nxt[t]]]=0;
continue;
}
if(nxt[t]==n)
{
rmov(1);
rmov(pos[prv[t]]);
nxt[prv[prv[t]]]=n;
continue;
}
int a=nxt[t],b=prv[t];
nxt[t]=nxt[a];prv[nxt[a]]=t;
prv[t]=prv[b];nxt[prv[b]]=t;
h[1].v=h[pos[a]].v+h[pos[b]].v-h[pos[t]].v;
down(1);
rmov(pos[a]);
rmov(pos[b]);
}
printf("%d\n",ans);
return 0;
}
update:
又写了一个 不用手写堆的(加个vis数组)
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,k;
int a[100005],prv[100005],nxt[100005];
bool vis[100005];
priority_queue<pair<int,int> >q;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
a[i-1]=a[i]-a[i-1];
}
for(int i=1;i<n;++i)prv[i]=i-1,nxt[i]=i+1,q.push(make_pair(-a[i],i));
int ans=0;
while(k--)
{
pair<int,int>tp=q.top();
q.pop();
int l=-tp.first,x=tp.second;
if(vis[x])
{
++k;
continue;
}
ans+=l;
if(prv[x]==0)
{
vis[nxt[x]]=true;
prv[nxt[nxt[x]]]=0;
}
else if(nxt[x]==n)
{
vis[prv[x]]=true;
nxt[prv[prv[x]]]=n;
}
else
{
a[x]=a[prv[x]]+a[nxt[x]]-a[x];
vis[prv[x]]=vis[nxt[x]]=true;
q.push(make_pair(-a[x],x));
prv[nxt[nxt[x]]]=x;
nxt[prv[prv[x]]]=x;
prv[x]=prv[prv[x]];
nxt[x]=nxt[nxt[x]];
}
}
printf("%d\n",ans);
return 0 ;
}