【链表】bzoj 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1136 Solved: 458
[Submit][Status][Discuss]
Description
Input
输入的第一行包含整数n和k,其中n(2 ≤ n ≤100 000)表示办公楼的数目,k(1≤ k≤ n/2)表示可利用的网络电缆的数目。接下来的n行每行仅包含一个整数(0≤ s ≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。
Output
输出应由一个正整数组成,给出将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。
Sample Input
5 2
1
3
4
6
12
1
3
4
6
12
Sample Output
4
HINT
上面的样例输入给出了前面描述的示例情形 对于每一个测试点,如果写到输出文件中的答案正确,则得到该测试点100%的分数,否则得零分。30%的输入数据满足n≤20。60%的输入数据满足n≤10 000。
一开始觉得要贪心什么的
瞄了一眼题解
貌似我再想一下能出来( 大雾
然后感觉好困。。
最后几乎是半抄完了
易得每次只能选相邻点
所有只有n-1条边可选
每次链表选最小的
然后选完后合并前一个和后一个
具体来说就是堆维护最小值
每次合并-->该边和上一条和下一条不可选,创建一个新的节点代替原来的三个,ans加上权值
权值是左边+右边-中间(再选新节点=不选中间选两边)
还有就是选队首队尾,则易得选队首的后一个和选队尾的前一个不可能优。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 7 #define maxn 1000001 8 9 using namespace std; 10 11 int a[maxn*2],n,k,pre[maxn*2],next[maxn*2],num=0; 12 13 long long cha[maxn*2],ans=0; 14 15 bool vis[maxn*2]; 16 17 struct node{ 18 int x; 19 long long c; 20 bool operator <(const node &A)const{ 21 if(A.c==c)return x>A.x; 22 return c>A.c; 23 } 24 }; 25 26 priority_queue<node>q; 27 28 inline int in() 29 { 30 int x=0;char ch=getchar(); 31 while(ch<'0'||ch>'9')ch=getchar(); 32 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 33 return x; 34 } 35 36 void Pre() 37 { 38 for(int i=1;i<n;i++) 39 cha[i]=a[i+1]-a[i],q.push((node){i,a[i+1]-a[i]}),pre[i]=i-1,next[i]=i+1; 40 num=n; 41 pre[n]=n-1;next[0]=1; 42 } 43 44 void solve() 45 { 46 node Top; 47 for(int i=1;i<=k;i++) 48 { 49 Top=q.top();q.pop(); 50 while(vis[Top.x]) 51 Top=q.top(),q.pop(); 52 if(pre[Top.x]==0) 53 { 54 pre[next[next[Top.x]]]=0; 55 ans+=Top.c; 56 vis[Top.x]=vis[next[Top.x]]=1; 57 } 58 else if(next[Top.x]==n) 59 { 60 next[pre[pre[Top.x]]]=n; 61 ans+=Top.c; 62 vis[Top.x]=vis[pre[Top.x]]=1; 63 } 64 else 65 { 66 ans+=Top.c; 67 node New; 68 New.x=++num; 69 New.c=cha[pre[Top.x]]+cha[next[Top.x]]-Top.c; 70 pre[New.x]=pre[pre[Top.x]],next[pre[New.x]]=New.x; 71 next[New.x]=next[next[Top.x]],pre[next[New.x]]=New.x; 72 vis[Top.x]=vis[next[Top.x]]=vis[pre[Top.x]]=1; 73 cha[num]=New.c; 74 q.push(New); 75 } 76 } 77 } 78 79 int main() 80 { 81 n=in();k=in(); 82 for(int i=1;i<=n;i++)a[i]=in(); 83 Pre();solve(); 84 printf("%lld",ans); 85 return 0; 86 }