洛谷 P3620 [APIO/CTSC 2007]数据备份(反悔贪心)

传送门


 

解题思路

种树这道题很像。

这个就是先差分求出每两个之间的间隔共n-1个,然后把这n-1个看做点,与种树一样处理。

注意因为要距离和最小,所以:

  • 要用小根堆
  • 要把a[0]和a[n]初始化成一个很大的数,因为在更新a[1]时要a[0]+a[2]-a[1],而0这个点我们不能选,所以初始化一个很大的数。(手推一下就知道了)

AC代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<queue>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn=100005;
 8 int n,k,s[maxn],a[maxn],l[maxn],r[maxn],ans;
 9 bool vis[maxn];
10 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
11 int main(){
12     cin>>n>>k>>s[0];
13     r[0]=1;
14     a[0]=a[n]=0x3f3f3f3f;
15     for(int i=1;i<n;i++){
16         scanf("%d",&s[i]);
17         a[i]=s[i]-s[i-1];
18         l[i]=i-1;
19         r[i]=i+1;
20         q.push(make_pair(a[i],i));
21     }
22     for(int i=1;i<=k;i++){
23         while(!q.empty()&&vis[q.top().second]) q.pop();
24         ans+=q.top().first;
25         int id=q.top().second;
26         q.pop();
27         vis[l[id]]=vis[r[id]]=1;
28         a[id]=a[l[id]]+a[r[id]]-a[id];
29         r[l[l[id]]]=l[r[r[id]]]=id;
30         l[id]=l[l[id]];
31         r[id]=r[r[id]];
32         q.push(make_pair(a[id],id));
33     }
34     cout<<ans;
35     return 0;
36 }

//APIO/CTSC 2007

 

posted @ 2020-11-05 20:31  尹昱钦  阅读(126)  评论(0编辑  收藏  举报