还是用堆维护双向链表来贪心= =
显然连起来的都是相邻的节点。。先把n-1条线段长度插进小根堆里。。
每次将ans加上堆顶的线段长,就是要取这条线段,然后再插入(左边的线段长+右边的线段长-堆顶线段长)。。其实就是取这条线段旁边的线段
一开始脑残没考虑到,对于左右两端的线段而言,一旦取了,那么就不用插入不取的情况(因为线段条数一样)。。吃了两发WA
优先队列大法好。。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=100023; 8 const int inf=1002333333; 9 struct zs{int id;}; 10 priority_queue<zs>q; 11 int pre[maxn<<1],next[maxn<<1],v[maxn<<1]; 12 bool del[maxn<<1]; 13 int i,j,k,n,m,tot,ans; 14 15 bool operator <(zs a,zs b){return v[a.id]>v[b.id];} 16 17 int ra;char rx; 18 inline int read(){ 19 rx=getchar(),ra=0; 20 while(rx<'0'||rx>'9')rx=getchar(); 21 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 22 } 23 24 int main(){ 25 n=read(),k=read(); 26 for(i=2,j=read();i<=n;i++,j=m)m=read(),v[++tot]=m-j; 27 for(i=1;i<n;i++)q.push((zs){i}),pre[i]=i-1,next[i]=i+1; 28 pre[1]=next[tot]=0;v[0]=inf; 29 while(k--){ 30 while(!q.empty()&&del[q.top().id])q.pop();if(q.empty())break; 31 int x=q.top().id,pr=pre[x],nex=next[x]; 32 ans+=v[x],del[x]=1,q.pop(), 33 del[pr]=del[nex]=1,v[++tot]=v[pr]+v[nex]-v[x],q.push((zs){tot}); 34 pre[tot]=pre[pr],next[tot]=next[nex]; 35 if(pre[tot])next[pre[tot]]=tot; 36 if(next[tot])pre[next[tot]]=tot; 37 } 38 printf("%d ",ans); 39 return 0; 40 }