1. 程式人生 > 實用技巧 >洛谷 P3620 [APIO/CTSC 2007]資料備份(反悔貪心)

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