洛谷 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