[bzoj1150] [CTSC2007]数据备份Backup

  还是用堆维护双向链表来贪心= =

  显然连起来的都是相邻的节点。。先把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 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5185809.html